| Sply Splyeff ( @ 2009-03-13 22:22:00 |
mysql query cache tips - таблицы преселектов
Мощная штука, но есть одна деталь, сильно уменьшающая пользу от кэша. Любое изменение любой таблицы из запроса выбрасывает все запросы из кэша. Но есть несложный прием, позволяющий за счет некритичной рассинхронизации содержать query cache намного эффективнее. Держать отдельные таблицы в качестве поставщиков данных для самых частых, но не критичных к свежести информации запросов. Которые наполнять с некоторой периодичностью, например, раз в 10 минут. При больших объемах данных можно держать и отдельные pre-selected таблицы по какому-то частому условию. И, конечно, денормировать.
Живой пример. Есть таблица wishes, имеющая поле visible := public | visible | friends-only | private. Когда для незалогиненного юзера (включая поисковых роботов) показывается лента, генерируемая по этой таблице, ко всем запросам добавляется условие public = visible. И запросы такие составляют почти половину от всех.
Убиваем двух зайцев с минимальными изменениями так:
- раз в 30 минут создаем пустую таблицы wishes_public, в которую выбираем все данные из wishes по условию visible = public
- в рельсах создаем новый класс модели WishesPublic
class WishPublic < Wish
set_table_name 'wishes_public'
end
и везде, где показывается публичная часть сайта, вместо класса Wish указывается WishPublic.
Если стремиться к сверхоптимизации, то можно было бы снимать в wishes_public индекс с поля visibe и убирать его из запросов, но это копейки по сравнению с основным эффектом. Разница в скорости селекта - от 4 до 50 раз в зависимости от типа запроса. Плюс к этому эффективность query cache повышается с 10% до 55% cache hit rate.
Мощная штука, но есть одна деталь, сильно уменьшающая пользу от кэша. Любое изменение любой таблицы из запроса выбрасывает все запросы из кэша. Но есть несложный прием, позволяющий за счет некритичной рассинхронизации содержать query cache намного эффективнее. Держать отдельные таблицы в качестве поставщиков данных для самых частых, но не критичных к свежести информации запросов. Которые наполнять с некоторой периодичностью, например, раз в 10 минут. При больших объемах данных можно держать и отдельные pre-selected таблицы по какому-то частому условию. И, конечно, денормировать.
Живой пример. Есть таблица wishes, имеющая поле visible := public | visible | friends-only | private. Когда для незалогиненного юзера (включая поисковых роботов) показывается лента, генерируемая по этой таблице, ко всем запросам добавляется условие public = visible. И запросы такие составляют почти половину от всех.
Убиваем двух зайцев с минимальными изменениями так:
- раз в 30 минут создаем пустую таблицы wishes_public, в которую выбираем все данные из wishes по условию visible = public
- в рельсах создаем новый класс модели WishesPublic
class WishPublic < Wish
set_table_name 'wishes_public'
end
и везде, где показывается публичная часть сайта, вместо класса Wish указывается WishPublic.
Если стремиться к сверхоптимизации, то можно было бы снимать в wishes_public индекс с поля visibe и убирать его из запросов, но это копейки по сравнению с основным эффектом. Разница в скорости селекта - от 4 до 50 раз в зависимости от типа запроса. Плюс к этому эффективность query cache повышается с 10% до 55% cache hit rate.