Цель статьи рассказать о том, что один метод AR сильно быстрее другого, а не о способах создать крутую баннерокрутилку. Возможно, я привел неудачный пример.
По п.1.: А если 2000 _разных_ баннеров показались 1 раз? :)
Насчет п.2 согласен абсолютно, yii мог бы отслеживать сам, что надо обновить только счетчик.
Просто тут речь не про хайлоад-счетчики, а про «бытовую» баннерокрутилку и про то, как оптимальнее использовать стандартный функционал СActiveRecord в Yii.
А то так и до nosql, и до шейдеров договоримся :)
Что значит собрать куда-нибудь? :)
updateCounters отличается от saveCounters тем, что изменяет значения во всей таблице, если не определено условие.
Ваш пример $banner->updateCounters(array('hits'=>$count)) увеличит счетчик у всех баннеров в таблице на +$count. Это как бы не то, что требуется :)
Чтобы изменить только некоторые строки, нужно написать кондишен, например, $banner->updateCounters(array('hits'=>1), 'id in (1,2,3)').
Это в итоге сформирует такой запрос UPDATE `banners` SET `hits`=`hits`+1 WHERE id in (1,2,3)
save вызовет колбэки beforeSave и afterSave, а это может сильно отразится на скорости, если они определены. false отрубает валидацию это конечно плюс, но saveCounters или updateByPk оптимальнее. см.коммент ниже.
В update вызываются колбэки beforeSave и afterSave.
А вот сравнение скорости таких конструкций
$banner->hits++;
$banner->updateByPk($banner->id,array('hits'=>$banner->hits));
и
$banner->saveCounters(array('hits'=>1));
показало одинаковый результат. saveCounters выглядит проще.
Сахар в общем :)
Между таблицами banners и banners_hits вы хотите сделать связь 1:1? Если так, думаю, выигрыша ни в чем не будет, в том числе в скорости обновления. Конечно, если обновлять через saveCounters или подобным быстрым способом.
>небольшой табличке.
так и banners небольшая… там ни в коем случает не хранится картинка или флэшка.
В отдельную таблицу стоит вынести счетчики, если связь 1: многим. Например, хиты сгруппированные по дням.
Не совсем понял, что вы предлагаете вынести?
Чтобы счетчики хитов были в другой таблице и сгруппированные, например, по суткам? В рамках задачи, которую я привел в качестве примера, ничего не требовалось :)
В другой подобной задаче делал так:
сырые данные складывались в memory-таблицу, по крону вызывался скрипт, который агрегировал в отдельную таблицу значения счетчиков таким хитрым запросом:
INSERT INTO {{stats}} SET id=:id, media=:media, created_at=NOW(), hits=1 ON DUPLICATE KEY UPDATE hits=hits+1
По п.1.: А если 2000 _разных_ баннеров показались 1 раз? :)
Насчет п.2 согласен абсолютно, yii мог бы отслеживать сам, что надо обновить только счетчик.
А то так и до nosql, и до шейдеров договоримся :)
updateCounters отличается от saveCounters тем, что изменяет значения во всей таблице, если не определено условие.
Ваш пример $banner->updateCounters(array('hits'=>$count)) увеличит счетчик у всех баннеров в таблице на +$count. Это как бы не то, что требуется :)
Чтобы изменить только некоторые строки, нужно написать кондишен, например, $banner->updateCounters(array('hits'=>1), 'id in (1,2,3)').
Это в итоге сформирует такой запрос UPDATE `banners` SET `hits`=`hits`+1 WHERE id in (1,2,3)
А вот сравнение скорости таких конструкций
$banner->hits++;
$banner->updateByPk($banner->id,array('hits'=>$banner->hits));
и
$banner->saveCounters(array('hits'=>1));
показало одинаковый результат. saveCounters выглядит проще.
Сахар в общем :)
>небольшой табличке.
так и banners небольшая… там ни в коем случает не хранится картинка или флэшка.
В отдельную таблицу стоит вынести счетчики, если связь 1: многим. Например, хиты сгруппированные по дням.
Чтобы счетчики хитов были в другой таблице и сгруппированные, например, по суткам? В рамках задачи, которую я привел в качестве примера, ничего не требовалось :)
В другой подобной задаче делал так:
сырые данные складывались в memory-таблицу, по крону вызывался скрипт, который агрегировал в отдельную таблицу значения счетчиков таким хитрым запросом:
если бы мне нужно было параллельное выполнение, то сделал как-то так: