Почему MySQL использует filesort в этом случае?

#mysql #sql #performance #optimization

#mysql #sql #Производительность #оптимизация

Вопрос:

Структура таблицы:

 CREATE TABLE IF NOT EXISTS `newsletters` 
(
    `id` int(11) NOT NULL auto_increment,
    `last_update` int(11) default NULL,
    `status` int(11) default '0',
    `message_id` varchar(255) default NULL,
    PRIMARY KEY  (`id`),
    KEY `status` (`status`),
    KEY `message_id` (`message_id`),
    KEY `last_update` (`last_update`)
) 
ENGINE=MyISAM DEFAULT CHARSET=latin1;
  

Запрос:

 SELECT id, last_update
FROM newsletters
WHERE status = 1
ORDER BY last_update DESC 
LIMIT 0, 100
  
  • newsletters в таблице более 3 миллионов записей
  • выполнение запроса занимает более 26 секунд

Запрос объясняет:

 id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  newsletters range   status  status  5   NULL    3043354 Using where; Using filesort
  

Итак, почему он не использует filesort , и как это range запрос?

Ответ №1:

Он используется filesort для сортировки по last_update . Вы можете избежать этого, изменив индекс на status, last_update , чтобы MySQL находил все строки со статусом 1 в правильном порядке.

Для дальнейшей оптимизации измените индекс на status, last_update, id . Это позволяет MySQL удовлетворять запрос, просто просматривая индекс, без поиска по таблице.

 CREATE INDEX idx_newsletters_status
ON newsletters(status, last_update, id);
  

Комментарии:

1. KEY должен применять индексы так же, как INDEX.

2. Это сделало это, я любитель в оптимизации / индексировании, поэтому я действительно не думал о попытке индексировать несколько столбцов. @Baez: Не могли бы вы, пожалуйста, что вы имеете в виду под этим?

3. @gAMBOOKa: Чтобы представить, какой индекс вам больше всего помог бы, попробуйте представить, какой список в каком порядке больше всего помог бы вам , если бы вы были компьютером, и вам нужно было быстро найти правильные записи и вернуть запрошенную информацию. В этом случае вам нужен список всех записей (поскольку каждый индекс должен содержать все записи), отсортированных сначала по статусу (поскольку вас интересуют только единицы), а затем по last_update (чтобы вы могли быстро получить первые 100 из них). Если вы добавите идентификатор в список, то сможете получить всю свою информацию без необходимости возвращаться к главной таблице.

4. Это очень интуитивный способ объяснить это. Итак, в принципе, я должен добавить индексы в том порядке, в котором будет удалено большинство строк слева направо, правильно?