@vasayxtx

MySql. Почему незначительное изменение limit'а может сильно влиять на производительность запроса?

Есть простой запрос с where, order by, limit вида (фильтра по атрибуту upped нет):
SELECT t.pid FROM purchases t  WHERE ... and t.status in (2, 15) and ... order by t.upped desc LIMIT 36;

Он выполняется ~1.35s, его результат - 26 строк. Explain:
type: index
key: upped
key_len: 9
rows: 2445
filtered: 88.43
extra: using where

Если мы в этом же запросе делаем limit <= 26, то запрос выполняется ~200ms. Explain:
type: index
key: upped
key_len: 9
rows: 1766
filtered: 122.42
extra: using where

Если мы в этом же запросе делаем limit >= 40, то запрос выполняется ~200ms. Explain:
type: range
key: status
key_len: 4
rows: 2160
filtered: 100.00
extra: Using index condition; Using where; Using filesort

Как видно, незначительные изменения limit'а сильно влияют на производительность. Если limit в диапазон [27..39], то запрос выполняется очень медленно, иначе - быстро. Причем началось это неожиданно, раньше запрос отрабатывал за не более 300ms. В чем может быть причина такого поведения? Кто-нибудь сталкивался с нечто подобным?

Таблица в innodb, всего в ней 248285 строк. Версия mysql: 5.6.23. Используем ssd диски.

CREATE TABLE `purchases` (
  `pid` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `megapurchases_id` int(10) unsigned DEFAULT NULL,
  `name` varchar(60) NOT NULL DEFAULT '',
  `uid` int(11) unsigned NOT NULL DEFAULT 0,
  `upped` datetime DEFAULT NULL,
  `changed` timestamp NULL DEFAULT NULL,
  `moderation_status` enum('wait_postmoderation','wait_premoderation','accepted','rejected','not_moderated') DEFAULT NULL,
  `status` int(3) unsigned NOT NULL DEFAULT 0,
  `purchase_type` tinyint(3) unsigned NOT NULL DEFAULT 0,
  `info_popularity` int(10) unsigned DEFAULT NULL,
  `published` timestamp NULL DEFAULT NULL,
  `rules` longtext,
  `description_good` text,
  `description_payment` text,
  `description_distributor` text,
  `info_user` longtext,
  `annotation` varchar(160) DEFAULT NULL,
  -- ... всего 60 атрибутов
  PRIMARY KEY (`pid`),
  KEY `uid` (`uid`),
  KEY `changed` (`changed`),
  KEY `moderation_status` (`moderation_status`),
  KEY `status` (`status`),
  KEY `purchase_type` (`purchase_type`),
  KEY `info_popularity` (`info_popularity`),
  KEY `published` (`published`),
  KEY `upped` (`upped`),
  KEY `purchases_megapurchases_id` (`megapurchases_id`)
) ENGINE=InnoDB AUTO_INCREMENT=249726 DEFAULT CHARSET=utf8;
  • Вопрос задан
  • 1382 просмотра
Пригласить эксперта
Ответы на вопрос 3
egor_nullptr
@egor_nullptr
Скорее всего, не всё табличное пространство помещается в памяти и часть страниц InnoDB подкачивает с диска.
Советы:
* Снижайте количество "rows" в выводе explain, для этого воспользуйтесь покрывающим индексом.
* Увеличьте параметр innodb_buffer_pool_size
Ответ написан
@porozhnyy
Покажите Ваши настройки MySQL... И посмотрите статистику БД, вернее её предупреждающие значения - если есть PHPMyAdmin можно в нем - Состояние - Все переменные состояние - Выводить только предупреждающие значения. Иногда вещи пишет...
Ответ написан
opium
@opium
Просто люблю качественно работать
Ручками укажите ему в запросе какой индекс использовать или какой индекс не использовать. К сожалению это косячит оптимизатор mysql. Можно ещё апдейтнуть мускул до последней версии в новых версиях оптимизатор чудит меньше
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы