У меня есть таблица mysql (статьи) с вложенным индексом (blog_id, опубликовано), и она работает плохо. Я вижу много таких в моих журналах медленных запросов:
- Query_time: 23.184007 Lock_time: 0.000063 Rows_sent: 380 Rows_examined: 6341
SELECT id from articles WHERE category_id = 11 AND blog_id IN (13,14,15,16,17,18,19,20,21,22,23,24,26,27,6330,6331,8269,12218,18889) order by published DESC LIMIT 380;
У меня проблемы с пониманием, почему mysql пробежал все строк с этими blog_ids, чтобы выяснить мои лучшие 380 строк. Я ожидаю, что вся цель вложенного индекса - ускорить его. По крайней мере, даже наивная реализация должна искать по blog_id и получать ее первые 380 строк, упорядоченных по опубликованным. Это должно быть быстро, так как мы можем вычислить точные 200 строк, благодаря вложенному индексу. А затем отсортировать получившиеся 19 * 200 = 3800 строк.
Если бы вы реализовали его наиболее оптимальным способом, вы бы поместили кучу из набора всех потоков, основанных на идентификаторах блогов, и выбрали один с максимальным (опубликовано) и повторили его 200 раз. Каждая операция должна быть быстрой.
Я определенно что-то упускаю, поскольку Google, Facebook, Twitter, Microsoft и все крупные компании используют mysql для производственных целей. Кто-нибудь с опытом?
Редактировать: Обновление в соответствии с ответом Тигера. Я попробовал намеки на указатель, но это не помогло. Результаты прилагаются ниже, в конце. Mysql заказ по оптимизации утверждает, что решает проблему, которую поднимает theiger:
Я согласен, что MySQL может использовать
составной блог_ид-опубликованного-индекса,
но только для части blog_id
запрос.
ВЫБРАТЬ * ОТ t1 ГДЕ
key_part1 = константа ORDER BY
key_part2;
Atleast mysql, похоже, утверждает, что его можно использовать не только в предложении WHERE (часть запроса blog_id). Любая помощь theiger?
Спасибо,
-Prasanna
[myprasanna в Gmail точка ком]
CREATE TABLE IF NOT EXISTS `articles` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`category_id` int(11) DEFAULT NULL,
`blog_id` int(11) DEFAULT NULL,
`cluster_id` int(11) DEFAULT NULL,
`title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`description` text COLLATE utf8_unicode_ci,
`keywords` text COLLATE utf8_unicode_ci,
`image_url` varchar(511) COLLATE utf8_unicode_ci DEFAULT NULL,
`url` varchar(511) COLLATE utf8_unicode_ci DEFAULT NULL,
`url_hash` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`author` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`categories` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`published` int(11) DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
`is_image_crawled` tinyint(1) DEFAULT NULL,
`image_candidates` text COLLATE utf8_unicode_ci,
`title_hash` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`article_readability_crawled` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_articles_on_url_hash` (`url_hash`),
KEY `index_articles_on_cluster_id` (`cluster_id`),
KEY `index_articles_on_published` (`published`),
KEY `index_articles_on_is_image_crawled` (`is_image_crawled`),
KEY `index_articles_on_category_id` (`category_id`),
KEY `index_articles_on_title_hash` (`title_hash`),
KEY `index_articles_on_article_readability_crawled` (`article_readability_crawled`),
KEY `index_articles_on_blog_id` (`blog_id`,`published`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=562907 ;
SELECT id from articles USE INDEX(index_articles_on_blog_id) WHERE category_id = 11 AND blog_id IN (13,14,15,16,17,18,19,20,21,22,23,24,26,27,6330,6331,8269,12218,18889) order by published DESC LIMIT 380;
....
380 rows in set (11.27 sec)
explain SELECT id from articles USE INDEX(index_articles_on_blog_id) WHERE category_id = 11 AND blog_id IN (13,14,15,16,17,18,19,20,21,22,23,24,26,27,6330,6331,8269,12218,18889) order by published DESC LIMIT 380\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: articles
type: range
possible_keys: index_articles_on_blog_id
key: index_articles_on_blog_id
key_len: 5
ref: NULL
rows: 8640
Extra: Using where; Using filesort
1 row in set (0.00 sec)