MySQL: оптимизация поиска по диапазону записей. - PullRequest
2 голосов
/ 16 января 2012

Я только что увидел очень медленный запрос в моем приложении. Таблица «Новости» содержит более 600 000 записей.

Когда я выполняю:

SELECT news.id FROM `news` WHERE (newstime between '2012-01-16 00:00:00' AND  '2012-01-16 23:59:59') AND ((MATCH(titolo, testo) AGAINST('"Public Administration" "SOMETHING" "ELSE" "ROMA" "MILANO"' IN BOOLEAN MODE))) ORDER BY newstime DESC LIMIT 23 OFFSET 0;
23 rows in set (26.32 sec)

По какой-то причине MySQL не выполняет выбор диапазона (для каждого дня есть только 10.000 записей), похоже, что он выполняет поиск по всей таблице, потому что, когда я выбираю из подзапроса:

 SELECT id FROM(SELECT * from news where newstime between '2012-01-16 00:00:00' AND  '2012-01-16 23:59:59') as N where ((MATCH(titolo, testo) AGAINST('"Public Administration" "FIAT" "SOMETHING" "ELSE" "ROMA" "MILANO"' IN BOOLEAN MODE))) ORDER BY newstime DESC LIMIT 23 OFFSET 0;

23 rows in set (0.09 sec)

Мой запрос возвращается через 0,09 секунды!

26 -> 0,09 секунды.

Я думал, что MySQL будет достаточно умен, чтобы выбирать диапазон записей по времени новостей и затем выполнять полнотекстовый поиск, но похоже, что это не так. Это нормально? Или я должен попытаться оптимизировать первый запрос? Когда я пишу объяснение № 1, оно говорит:

mysql> explain SELECT news.id FROM `news` WHERE (newstime between '2012-01-16 00:00:00' AND  '2012-01-16 23:59:59') AND ((MATCH(titolo, testo) AGAINST('"Public Administration" "FIAT" "SOMETHING" "ELSE" "ROMA" "MILANO"' IN BOOLEAN MODE))) ORDER BY newstime DESC LIMIT 23 OFFSET 0;
+----+-------------+-------+----------+--------------------------------+---------+---------+------+------+-----------------------------+
| id | select_type | table | type     | possible_keys                  | key     | key_len | ref  | rows | Extra                       |
+----+-------------+-------+----------+--------------------------------+---------+---------+------+------+-----------------------------+
|  1 | SIMPLE      | news  | fulltext | index_news_on_newstime,alltext | alltext | 0       |      |    1 | Using where; Using filesort |
+----+-------------+-------+----------+--------------------------------+---------+---------+------+------+-----------------------------+

Почему используется полнотекстовый ключ, а не новостное время?

Показать новость создания таблицы следующим образом:

 CREATE TABLE `news` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `titolo` varchar(255) DEFAULT NULL,
  `testo` mediumtext,
  `newstime` datetime NOT NULL,
  `created_at` datetime DEFAULT NULL
  PRIMARY KEY (`id`),
  KEY `index_news_on_newstime` (`newstime`),
  FULLTEXT KEY `alltext` (`titolo`,`testo`)
) ENGINE=MyISAM AUTO_INCREMENT=1846714 DEFAULT CHARSET=utf8 |

Почему это?

1 Ответ

5 голосов
/ 16 января 2012

Ответ на вопрос «почему?» просто оптимизатор запросов MySQL не идеален. Иногда он выбирает менее оптимальный показатель. Вы можете исправить это, указав MySQL, какой индекс использовать с индексными подсказками

SELECT news.id 
FROM `news` 
USE INDEX (index_news_on_newstime) 
WHERE (newstime between '2012-01-16 00:00:00' AND  '2012-01-16 23:59:59') 
  AND ((MATCH(titolo, testo) AGAINST('"Public Administration" "SOMETHING" "ELSE" "ROMA" "MILANO"' IN BOOLEAN MODE))) 
ORDER BY newstime DESC LIMIT 23 OFFSET 0;

Из документов: "Вы также можете использовать FORCE INDEX, который действует как USE INDEX (index_list), но с добавлением, что сканирование таблицы предполагается очень дорогим. Другими словами, сканирование таблицы используется только в том случае, если нет способа используйте один из указанных индексов, чтобы найти строки в таблице. "

SELECT news.id 
FROM `news` 
FORCE INDEX (index_news_on_newstime) 
WHERE (newstime between '2012-01-16 00:00:00' AND  '2012-01-16 23:59:59') 
  AND ((MATCH(titolo, testo) AGAINST('"Public Administration" "SOMETHING" "ELSE" "ROMA" "MILANO"' IN BOOLEAN MODE))) 
ORDER BY newstime DESC LIMIT 23 OFFSET 0;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...