我有一个相当简单的查询,大约需要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()”命令几乎立即返回。
答案 0 :(得分:2)
您所拥有的必须使用5列索引遍历所有行,然后对结果进行排序并提供100行。
唯一可能有用的索引是INDEX(cid, links)
。这是因为cid
是唯一使用=
进行测试的列,然后links
可能对ORDER BY
和{{1}有用}。 LIMIT
测试仍然存在过滤大量行的风险。
!=
和status
多值?如果其中任何一个只有2个值,那么将otype
转换为!=
并将其添加到索引中将是有益的。
您真的需要所有列(=
)吗?如果没有,和你不需要任何大的列(SELECT *
),那么你可以使用'覆盖'索引。
答案 1 :(得分:2)
使用不等式比较很有趣,它们被视为范围条件。
即,等于匹配一个值,但除了相等之外的任何值(!=
,>
,<
,IN
,BETWEEN
)。
通过匹配多个值,意味着只会优化范围条件中使用的索引中的第一列。您认为您的索引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)