优化mySQL中特定查询的索引

时间:2016-11-30 19:43:51

标签: mysql sql query-performance

我有一个相当简单的查询,大约需要14秒才能完成,我想加快速度。我认为我有正确的索引,但我不确定......

以下是查询

SELECT *
FROM opportunities
WHERE cid = 7785
  AND STATUS != 4
  AND otype != 200
  AND links > 0
  AND ontopic != 'F'
ORDER BY links DESC
LIMIT 0, 100;

以下是表格架构

CREATE TABLE `opportunities` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `cid` int(11) NOT NULL,
  `url` varchar(900) CHARACTER SET utf8 NOT NULL,
  `status` tinyint(4) NOT NULL,
  `links` int(11) NOT NULL,
  `otype` int(11) NOT NULL,
  `reserved` tinyint(4) NOT NULL,
  `ontopic` varchar(3) CHARACTER SET utf8 NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `cid` (`cid`,`url`),
  KEY `cid1` (`cid`),
  KEY `url` (`url`),
  KEY `otype` (`otype`),
  KEY `reserved` (`reserved`),
  KEY `ontopic` (`ontopic`),
  KEY `status` (`status`),
  KEY `links` (`links`),
  KEY `ontopic_links` (`ontopic`,`links`),
  KEY `cid_status_otype_links_ontopic` (`cid`,`status`,`otype`,`links`,`ontopic`)
) ENGINE=InnoDB AUTO_INCREMENT=13022832 DEFAULT CHARSET=latin1

以下是EXPLAIN命令的结果

id: 1
select_type: Simple
table: opportunities
partitions: null
type: range
possible_keys: cid,cid1,otype,ontopic,status,links,ontopic_links,cid_status_otype_links_ontopic
key: links
keylen: 4
ref: null
rows: 1531552
filtered: 0.33
Extra: Using index condition; Using where

思考/问题

我是否正确地阅读了它正在使用“链接”键进行查询?为什么不使用更完整的索引,比如cid_status_otype_links_ontopic,它涵盖了我的查询的所有条件?

提前致谢!

根据要求

当您删除LIMIT 0,100时,有30,961个结果与查询匹配。有趣的是,“count()”命令几乎立即返回。

2 个答案:

答案 0 :(得分:2)

  • 您所拥有的必须使用5列索引遍历所有行,然后对结果进行排序并提供100行。

  • 唯一可能有用的索引是INDEX(cid, links)。这是因为cid是唯一使用=进行测试的列,然后links 可能ORDER BY和{{1}有用}。 LIMIT测试仍然存在过滤大量行的风险。

  • !=status多值?如果其中任何一个只有2个值,那么将otype转换为!=并将其添加到索引中将是有益的。

  • 您真的需要所有列(=)吗?如果没有,你不需要任何大的列(SELECT *),那么你可以使用'覆盖'索引。

More on writing indexes

答案 1 :(得分:2)

使用不等式比较很有趣,它们被视为范围条件。

即,等于匹配一个值,但除了相等之外的任何值(!=><INBETWEEN)。

通过匹配多个值,意味着只会优化范围条件中使用的索引中的第一列。您认为您的索引cid_status_otype_links_ontopic包含查询条件中提到的所有列,但只会使用前两个。第一个因为你有cid的相等比较。第二个是因为下一列用于不等式比较,然后用于停止使用索引中的列。*

证据:如果您可以强制使用该索引,则应该看到EXPLAIN结果的keylen字段仅显示5,其大小为cid(4个字节)+ {{ 1}}(1个字节)。

MySQL优化器显然预测使用status索引会更有利,因为它允许它以索引顺序访问行,这与您使用{请求的排序顺序相同{1}}。

证据:您没有看到&#34;使用filesort&#34;在你的EXPLAIN笔记中。

这真的比使用其他索引更好吗?也许,也许不是。优化程序的预测并不总是完美的。

您可以使用index hint覆盖优化程序的选择:

links

尝试一下,执行该查询的EXPLAIN并将其与其他EXPLAIN进行比较。然后执行两个查询,看看哪个查询可靠得快。

(*实际上,我必须添加一个关于索引列用法的脚注。当您看到注释&#34;使用索引条件&#34;时,MySQL 5.6及更高版本可以比两列更好一点。在EXPLAIN中。但它并不完全相同。你可以在这里阅读更多相关内容:https://dev.mysql.com/doc/refman/5.6/en/index-condition-pushdown-optimization.html