我有一个基于3列的复合索引,其中两列在我的查询中受到限制,而第三列是在by by子句中,而mysql不使用索引进行排序。
explain select * from videos where public_private='public' and approved='yes' order by number_of_views desc; +----+-------------+--------+------+--------------------------------+------+---------+------+---------+-----------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+------+--------------------------------+------+---------+------+---------+-----------------------------+ | 1 | SIMPLE | videos | ALL | approved,approved_3,approved_2 | NULL | NULL | NULL | 1476818 | Using where; Using filesort | +----+-------------+--------+------+--------------------------------+------+---------+------+---------+-----------------------------+
表结构如下:
CREATE TABLE `videos` (
`indexer` int(9) NOT NULL auto_increment,
`user_id` int(9) default NULL,
`public_private` varchar(24) default NULL,
`approved` varchar(24) default NULL,
`number_of_views` int(9) default NULL,
PRIMARY KEY (`indexer`),
KEY `approved` (`approved`,`user_id`),
KEY `approved_3` (`approved`,`public_private`,`indexer`),
KEY `approved_2` (`approved`,`public_private`,`number_of_views`),
) ENGINE=MyISAM AUTO_INCREMENT=1969091 DEFAULT CHARSET=utf8 |
如何强制mysql使用索引对结果进行排序?
答案 0 :(得分:13)
我相信您的查询可能与表中的大部分数据相匹配。在这种情况下,MySQL优化器通常选择进行表扫描并完全忽略索引,因为它实际上比通过额外读取整个索引并使用它来挑选数据的麻烦更快。所以在这种情况下,我猜测public_private='yes' and approved='yes'
匹配你桌子的很大一部分。因此,如果MySQL因此而跳过使用索引,那么它也不能用于排序。
如果您真的希望它使用索引,那么解决方案就是使用FORCE INDEX
:
select * from videos FORCE INDEX (approved_2) where public_private='public' and approved='yes' order by number_of_views desc;
但是,我会运行一些测试来确保你获得的内容实际上比MySQL优化器选择的更快。显然,优化器does have some issues可以选择订购,所以你绝对可以试一试,看看你是否获得了更好的性能。
答案 1 :(得分:1)
订单在复合键中很重要。如果您想使用number_of_views
键仅按approved_2
排序,请更改:
KEY `approved_2` (`approved`,`public_private`,`number_of_views`)
为:
KEY `approved_2` (`number_of_views`,`approved`,`public_private`)
MySQL中的复合键从左到右工作。在上面的示例中,使用number_of_views
,approved
和public_private
隐含声明的密钥会在以下位置创建索引:
number_of_views
number_of_views
,approved
number_of_views
,approved
,public_private
答案 2 :(得分:0)
这应该有效:
`select * from videos where approved='yes' and public_private='public' order by number_of_views desc;`
如果没有,只需在number_of_views
上创建一个单独的索引。
这必须有效。
(mysql基本上遵循左右序列。因此,如果不在此序列中使用,approved
,public_private
,number_of_views
上的索引将无效。即,您可以使用所有三个从左边开始,从左边开始,从左边开始,或者从最左边开始。但是如果你不使用最左边的那个,它将无法工作,这就是这个想法。)
使用单独的索引会自动对number_of_views
进行排序,这可能对order by
有所帮助 - 我相信这一点。
答案 3 :(得分:-2)
订单在复合键中很重要。我忘记了规则,但尝试的顺序不同。
答案 4 :(得分:-2)
在number_of_views
列上添加单独的索引,然后查看它是否有效。
如果某个键是3列的组合,则只有在使用全部3个键执行操作时才会使用该特定键