问题
我有一个大约200万行(115 MB)的表,而且它的数量要大得多。当在桌面上运行一些实用程序脚本时,我注意到我的一个查询花了很长时间(15秒以上),当一个几乎相同的查询之前花了不到半秒钟。以下是查询:
查询1:
SELECT `id` FROM `my_table` WHERE `my_column`='test' ORDER BY `id` LIMIT 28000, 1000
Execution time: 0.204 seconds
查询2:
SELECT `id` FROM `my_table` WHERE `my_column`='test' ORDER BY `id` LIMIT 29000, 1000
Execution time: 10.203 seconds
索引和表格信息
id
是主键,my_column
也被编入索引(尽管目前其基数仅为1)
•id是一个int
•my_column是varchar(50)
查询解释
查询1:输入:index, possible_keys :my_column,键:PRIMARY, key_len :4, 行:29,000,额外:使用
查询2:输入:范围, possible_keys :my_column,键:my_column, key_len: 53, 行:2,139,123 额外:使用where;使用filesort
正如您所看到的,第二个查询正在使用my_column
键和filesort并且永远占用,但我所做的只是将限制偏移量增加1,000。
我如何暂时解决问题
1)如果我删除了WHERE my_column = 'test'
条件,mysql优化器正确地使用主键进行排序,但我无法删除这个条件,因为很快就会在my_column
中有其他值我需要过滤掉这个查询。
2)如果我使用FORCE INDEX (PRIMARY)
,mysql优化器也将使用正确的索引,但这似乎是一种黑客攻击。
我的问题
为什么mysql确实选择使用my_column
索引而不是主键?是否有更好的方法可以在表定义,索引或我的查询结构中处理它?</ p>
答案 0 :(得分:3)
我会尝试在(my_column, id)
。
答案 1 :(得分:0)
这很奇怪。您是否尝试过添加综合索引?
ALTER TABLE `my_table` ADD INDEX (id, my_column);
如果你只选择id并且总是只在where子句中使用my_column,这应该可以正常工作。
答案 2 :(得分:0)
使用当前设置,有两种显而易见的方法可以执行查询。
id
顺序检索行,并丢弃那些与WHERE
子句不匹配的行。WHERE
子句匹配的行,并按id
顺序对其进行排序。据推测,MySQL根据你想要的行数来猜测使用哪种方式。
但是,如果您在my_column
和id
上创建索引,则MySQL可以按my_column, id
顺序检索行,从my_column = 'test'
的第一行开始。
请注意,在一般情况下,这要求WHERE
子句中的所有条件都相等,并且WHERE
子句中的所有列都存在于索引中。