SELECT по значению столбца MIN и столбец CHAR очень медленный в MySQL

Я разумно уверен, что ответ на этот вопрос заключается в наличии другого индекса. У меня есть запрос, который неоправданно медленный, но только когда он находится в следующей полной форме, если я удалю части запроса, он будет молниеносно быстрым, как я могу его улучшить?

Медленный:

SELECT json
  FROM requests
  WHERE spider = 'foo'
    AND load_count = ( SELECT MIN( load_count ) FROM requests )
    AND load_count < 50
  LIMIT 500;

ОБЪЯСНЯТЬ:

+----+-------------+----------+------+-------------------------+--------------+---------+-------+--------+------------------------------+
| id | select_type | table    | type | possible_keys           | key          | key_len | ref   | rows   | Extra                        |
+----+-------------+----------+------+-------------------------+--------------+---------+-------+--------+------------------------------+
|  1 | PRIMARY     | requests | ref  | load_count,spider_index | spider_index | 90      | const | 200845 | Using where                  |
|  2 | SUBQUERY    | NULL     | NULL | NULL                    | NULL         | NULL    | NULL  |   NULL | Select tables optimized away |
+----+-------------+----------+------+-------------------------+--------------+---------+-------+--------+------------------------------+

Структура базы данных:

CREATE TABLE `requests` (
  `added` int(11) NOT NULL AUTO_INCREMENT,
  `url` char(255) NOT NULL,
  `spider` char(30) NOT NULL,
  `referer` char(255) DEFAULT NULL,
  `json` text NOT NULL,
  `load_count` int(11) NOT NULL DEFAULT '0',
  `processed` tinyint(1) NOT NULL DEFAULT '0',
  `invalid` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`added`),
  UNIQUE KEY `url` (`url`),
  KEY `load_count` (`load_count`),
  KEY `spider_index` (`spider`)
) ENGINE=MyISAM AUTO_INCREMENT=5285840 DEFAULT CHARSET=utf8

После обновления моего индекса, как предложил Нео, я получаю радикальные улучшения:

+----+-------------+----------+------+-------------------+-------------------+---------+-------------+------+------------------------------+
| id | select_type | table    | type | possible_keys     | key               | key_len | ref         | rows | Extra                        |
+----+-------------+----------+------+-------------------+-------------------+---------+-------------+------+------------------------------+
|  1 | PRIMARY     | requests | ref  | spider_load_count | spider_load_count | 94      | const,const | 1487 | Using where                  |
|  2 | SUBQUERY    | NULL     | NULL | NULL              | NULL              | NULL    | NULL        | NULL | Select tables optimized away |
+----+-------------+----------+------+-------------------+-------------------+---------+-------------+------+------------------------------+

person Kit Sunde    schedule 07.04.2011    source источник
comment
Проверьте, что произойдет, когда вы добавите EXPLAIN в свой оператор SELECT, он расскажет вам, что делает MySQL.   -  person Michael J.V.    schedule 07.04.2011
comment
Вы изучили план запроса?   -  person Stephen Chung    schedule 07.04.2011
comment
Добавление такого простого ограничения не должно замедлять выполнение запроса...   -  person Stephen Chung    schedule 07.04.2011
comment
Похоже, вы запускаете запрос (медленно), а затем извлекаете его из кеша. Использование EXPLAIN SELECT должно сообщить вам, какие поля mysql хочет использовать или использует для планирования запросов.   -  person Michael J.V.    schedule 07.04.2011
comment
Добавил EXPLAINS, и вы правы, я, должно быть, извлекал из кеша на быстрых.   -  person Kit Sunde    schedule 07.04.2011
comment
Вы можете тестировать запросы с помощью SELECT SQL_NO_CACHE .... (ничего не будет делать, если запрос уже кэширован, вы также можете очистить кэши). EXPLAIN EXTENDED — ваш друг, и для ваших целей профилирование может оказаться полезным — dev.mysql.com/tech-resources/articles/   -  person Unreason    schedule 07.04.2011
comment
Для объяснения объяснения проверьте stackoverflow.com/questions/1992312/, ваш запрос должен быть быстрым - здесь может быть полезен профилировщик, чтобы выяснить, что происходит.   -  person Unreason    schedule 07.04.2011
comment
@Unreason - я никогда раньше не видел SQL_NO_CACHE, это пригодится. Спасибо.   -  person Kit Sunde    schedule 07.04.2011
comment
@Kit Sunde, используйте с осторожностью - это для чистого кеша запросов, mysql по-прежнему будет кэшировать некоторые вещи (я думаю, что в основном это связано с индексами). Кроме того, эталонные тесты кэшированных результатов для частей базы данных, которые редко обновляются, могут быть более важными для производительности в рабочей среде.   -  person Unreason    schedule 07.04.2011


Ответы (2)


Что насчет этого?

SELECT MIN(load_count) INTO @min_load_count FROM requests;

SELECT json
  FROM requests
  WHERE load_count = @min_load_count
    AND load_count < 50
  LIMIT 500;

И наличие индекса в поле паука может вам помочь.

person Devart    schedule 07.04.2011
comment
Запрос ничего не улучшил, поскольку кажется, что MySQL уже оптимизировал внутренний запрос, и у меня есть индекс для паука, как вы можете видеть в CREATE TABLE в моем вопросе. - person Kit Sunde; 07.04.2011

Несколько замечаний/предложений:

  • Пробовали ли вы использовать оператор объяснения MySQL в инструкции Slow SELECT? ? Это, вероятно, даст вам некоторое представление о проблеме.
  • Я подозреваю, что проблема с медленным запросом заключается в том, что в предложении WHERE есть и паук, и load_count, но нет индекса, охватывающего оба поля. Добавление индекса с обоими, вероятно, исправит этот пример.
  • Первые два запроса имеют «AND load_count ‹ 50» в WHERE, что не требуется, поскольку у вас также есть «load_count = [точное значение]». MySQL будет игнорировать «AND load_count ‹ 50» при оптимизации запросов.
person pkt1975    schedule 07.04.2011
comment
1) Добавлены пояснения. 2) Я пытаюсь сделать это сейчас, согласно предложению Неоса. 3) Если количество MIN выше 50, мне не нужна строка. Так что это необходимо. - person Kit Sunde; 07.04.2011