По мере роста популярности ресурса, которым я заведую, нагрузки на сервер возросли кратно. Описанные ранее техники оптимизации исчерпали свой ресурс. Все индексы были созданы, все limit проставлены и из всех select'ов пропали звезды. Этого хватило не надолго. Через какое-то время, обычные запросы начали работать, как за 0.0002 сек, так и за 5. Как ускорить загрузку страницы в несколько раз?
Если бы это была база на несколько миллионов записей то тут можно было бы развести руками и сказать, что индекс сам по себе уже так разбавлен, что поиск по индексу тоже занимает время. Но в тормозящей таблице было не больше 700000 записей.
В поисках ответа я нашел интересную особенность таблиц MyISAM. Таблицы на этом движке, в отличие от таблиц на InnoDB поддерживают вставку данных, во время select операций. А это и было основной проблемой. Поэтому иногда
update users set visit_cnt=visit_cnt+1 where id=123
выполнялся за 0.0002 сек а иногда и за все 5. Просто в момент записи, к базе был постоянный коннект с запросом выборки данных. Соответственно update данных притормаживал на время выполнения запроса.
ALTER TABLE users ENGINE = MYISAM
Сменив движок, проблемы как водится не ушли. Был прирост скорости, но сайт все равно при каждом запросе зависал на 1-2 секунды.
Тут я вспомнил про антибот систему, которую написал с год назад. Она фиксировала все заходы определенного ip и записывала счетчик посещений этого ip в базу. Т.е. при любом запросе, будь то AJAX или обычная загрузка страницы, производится запись в эту таблицу.
Убирать эту защиту, по понятным причинам убирать я не стал. У нее было свое предназначение. Значит надо было как-то ускорить добавление и обновление этой таблицы.
Известно, что сайты которые грузятся быстро более любят поисковые системы. А значит, без оптимизации SQL запросов нормальное продвижения сайта сделать нельзя. Особенно, когда нужно сделать продвижение сайтов в Петербурге, где конкуренция очень высокая.
Из всех самых быстрых типов таблиц, наибыстрейшей является Memory. Этот тип таблиц не стоит использовать для хранения важных данных, таких как к примеру users. При сбое в работе MySQL или при его перезагрузке, все данные из таблицы удаляются.
Но мой случай, когда надо было локально контролировать поведение юзера, и не давать ему сделать больше запросов, чем может сделать живой человек. И таблица с типом memory подходит тут, как нельзя больше. данные из таблицы нужны были максимум на час. Потом их актуальность терялась. Простой запрос
ALTER TABLE `log` ENGINE = Memory
И сервер просто летает.