Взялись оптимизировать работу с БД, разобрались с индексами, теперь практически все запросы идут с Using where.
Проблема в том, что отрабатывают они быстро только при условии выгрузки главной таблицы в пул (нас в основном интересует одна таблица размером в 1Гб и 1млн. записей), узнаю я о том, что таблица выгружается в пул по стрекотанию харда.
Рядовой запрос с выгрузкой в пул (например, после перезапуска mysql) может выполняться и 60-70 секунд, что будет категорически неприемлемо для продакшна. Последующие разные запросы из той же таблицы уже отрабатывают за приемлемые 0.3-0.8 сек.
Проблема усугубляется тем, что периодически (вроде как после какого-то времени простоя) таблица оказывается выгруженной из пула, и читается туда снова, то есть ситуация 60-70 секунд на запрос может случаться не обязательно только при перезагрузке, а как-то случайным образом (возможно, и не случайным, тут не знаю).
Вопрос 1 — а вообще нормально, что запрос с Using where по таблице не в пуле выполняется 60-70 секунд?
Вопрос 2 — что можно сделать с проблемой выгрузки таблицы из пула?
Проблема решилась, итог такой - на работу Buffer Pool сильно влияет общее количество innodb-таблиц. Оставили на машине только нужные таблицы, справочные таблицы перевели на MyISAM, в итоге буфер устаканился и больше не вываливался, всё начало работать, как часы.
Проблема в том, что отрабатывают они быстро только при условии выгрузки главной таблицы в пул (нас в основном интересует одна таблица размером в 1Гб и 1млн. записей),
Я всегда считал, что в оперативной памяти должны быть все индексы, а не вся таблица. Иначе это была бы полная глупость. Откуда уверенность что вся таблица читается? Может у Вас просто большие индексы и мало памяти?
Проблема усугубляется тем, что периодически (вроде как после какого-то времени простоя) таблица оказывается выгруженной из пула, и читается туда снова
А во время простоя запросы к другим таблицам не делаете? Есть ли таблицы с огромными блобами (типа, файлы в базе храните)?
Насчет индексов в памяти я уверен потому, что специально это проверял.
Делал вычитку только индексов сразу после перезагрузки сервера.
Любой следующий запрос, использующий не только покрывающие индексы, вызывал вычитку таблицы.
Я всегда считал, что в оперативной памяти должны быть все индексы, а не вся таблица.
Buffer pool и для данных и для индексов. Большие данные выкинут индексы (поэтому я и спросил про файлы в БД).
Тем не менее для быстрой работы запросов в памяти нужны только индексы (в противном случае база будет всегда тормозить, если не влезет в память), по крайней мере у меня 30гб база нормально работает, запросы ок, хотя памяти у меня меньше 30 гб.
> Делал вычитку только индексов сразу после перезагрузки сервера.
как это делается?
> Любой следующий запрос, использующий не только покрывающие индексы
что такое покрывающие индексы?
Индекс может выкинуть из памяти какой-нибудь запрос, который читает все данные (работая без индекса), если, конечно, памяти мало.
На случай, если проблему решить не сможете — попробуйте сделать денормализацию — разбить таблицу на две. В одной оставьте столбцы, необходимые для выполнения запроса, в другой остальные. Тогда загружаться будет не гиг, а меньше. Да, в логику приложения придётся внести изменения.
— не хватает оперативы для кэш ОС либо неоптимальное (двойное либо наоборот одинарное) кэширование файлов таблиц mysql либо просто не хватает оперативы под буфера mysql. попробуйте уменьшить innodb_buffer_pool_size до 4х или 3х гигов. ещё у вас отводится память под myisam, key_buffer_size — полтора гига. оно действительно нужно? если не используете myisam — отключите его совсем
Включение innodb_file_per_table=1 можно совместить с денормализацией, тогда файл с данными для выборки можно уменьшить на порядок, что скажется на скорости чтения с диска.
Используем, есть совсем большая таблица полигонов, оно для этого.
Но, как я понимаю, на InnoDB это может влиять только со стороны размера памяти под этот key_buffer_size, и больше никак.
у вас наверное вся база в одном файле
Да, так.
Не делим на файлы пока только потому, что явной необходимости не было, а дамп/раздамп займёт немало времени.
О денормализации думаем, но пока нет понимания текущей ситуации, браться за такое не хотелось бы.
И ещё добавлю. Using where означает неоптимальное построение индексов. При правильном запросе и правильном построении индексов мускулу не требуется загружать всю таблицу, достаточно загрузить только индекс. Покажите структуру таблицы и проблемный запрос.
Я бы начал с этой меры в первую очередь.
У нас около 40 полей, участвующих в поиске, плюс сложные сортировки, поэтому совсем уйти от Using where не выйдет точно (после сортировок и флажков состояний от лимита составного индекса в 16 штук остаётся не так много).
Сама ситуация нахождения таблицы в памяти, в принципе, не проблема — её должно хватать на все таблицы (правда, есть сомнение, что количество памяти, требуемое под таблицу в пуле не совсем равно размеру таблицы на диске, и если это так, неплохо бы знать формулу расчета).
Проблема уже не в конкретных запросах.
Примеры запросов в студию, все таки засунуть все в память хорошо, но опять таки если все таблицы иннодб влезают, если их у вас больше чем буфер то понятно откуда идет вытеснение.
А прикрутить индексы не удалось к запросам?
Здесь у меня как раз всплывает ещё один вопрос — habrahabr.ru/qa/49454/#comment_232158
На дев-сервере, где тестируется всё это дело, есть ещё несколько БД с InnoDB-таблицами, которые просто не используются.
usage where это как раз не использование индексов это бегать по всей таблице, а при большом наборе данных это идиотизм, который выльется в стоящий колом сервер,
ну так уберите эти таблицы для тестов то своих