需要帮助优化 mysql 查询以使其按索引快速排序

Posted

技术标签:

【中文标题】需要帮助优化 mysql 查询以使其按索引快速排序【英文标题】:Need help optimizing mysql query to get it to sort quickly by index 【发布时间】:2013-04-19 20:56:16 【问题描述】:

有人帮我想出了这个查询,但它仍然太慢; order by 正在减慢它的速度,我认为它没有使用我的索引 我希望有人可以为我修复它:D 是的,我阅读了 manual 页面,但我无法理解。

查询:

 EXPLAIN SELECT u.id, u.url, u.title, u.numsaves
 FROM urls u
 JOIN tags t ON t.url_id = u.id
 AND t.tag = 'osx'
 ORDER BY u.numsaves DESC
 LIMIT 20 

 Showing rows 20 - 19 ( 20 total, Query took 1.5395 sec) [numsaves: 6130 - 2107]


 id     select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
 1  SIMPLE  t   ref     tag_id  tag_id  767     const   49432   Using where; Using index; Using temporary; Using filesort
 1  SIMPLE  u   eq_ref  PRIMARY,id_numsaves_IX  PRIMARY     4   jcooper_whatrethebest_urls.t.url_id     1   

数据库:

 CREATE TABLE `urls` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `url` text NOT NULL,
 `domain` text,
 `title` text NOT NULL,
 `description` text,
 `numsaves` int(11) NOT NULL,
 `firstsaved` varchar(256) DEFAULT NULL,
 `md5` varchar(255) NOT NULL DEFAULT '',
 PRIMARY KEY (`id`),
 UNIQUE KEY `md5` (`md5`),
 KEY `id_numsaves_IX` (`id`,`numsaves`)
 ) ENGINE=InnoDB AUTO_INCREMENT=2958560 DEFAULT CHARSET=utf8

 CREATE TABLE `tags` (
 `url_id` int(11) DEFAULT NULL,
 `hash` varchar(255) NOT NULL,
 `tag` varchar(255) NOT NULL,
 UNIQUE KEY `tag_id` (`tag`,`url_id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8

【问题讨论】:

我想我在摆弄这个时让 sqlfiddle 崩溃了。 :( 【参考方案1】:

我认为您查询的主要问题是您对索引的选择。

1) tagstagurl_id 上有一个复合 UNIQUE KEY,但没有 PRIMARY KEY

如果没有别的,您应该将其设为主要 - 这可能对性能有所帮助。此外,如果您的标签确实需要VARCHAR(255),您可能需要仔细查看。它使索引相当大。

2) 在numsaves 上添加一个单独的索引,因为您是按此排序的。 idnumsaves 上的复合索引在这里没有帮助。

3) EXPLAIN 表示tags 中有 49432 行与 "osx" 匹配。这是相当多余的。您可能希望将标签表分成两份,一份包含文本,另一份包含指向urls 的 N:M 链接。

【讨论】:

以上是关于需要帮助优化 mysql 查询以使其按索引快速排序的主要内容,如果未能解决你的问题,请参考以下文章

MySQL——索引原理与慢查询优化

MySQL之索引原理和慢查询优化

MySQL5.7性能优化系列——SQL语句优化——使用物化策略优化子查询

数据库索引原理及优化

MySQL 索引优化指南

MySQL SQL优化之‘%’