我正在处理一个看似奇怪的情况,只是从MySQL查询返回的数据量会导致使用或不使用明显的索引。
我们有一个名为“items”的表,其中包含一个名为type
的索引列。 Type是tinyint(3),非null值。无论是垂直还是水平,这个表都很大,而且确实有很长的奇异索引列表。
在许多情况下,在where字段中指定type
并按照预期工作时选择此表,以及type
字段上的索引。
EXPLAIN SELECT item.itemid, item.`type` FROM item WHERE item.`type` IN (1,40);
例如,工作正常。
SIMPLE item range type type 2 null 1634830 Using where; Using index
但是,添加一个不相关的返回字段,突然它不再使用索引。
EXPLAIN SELECT item.itemid, item.`type`,item.dir FROM item WHERE item.`type` IN (1,40);
1 SIMPLE item ALL type null null null 3514503 Using where
dir
字段并不是非常有趣......它只是一个布尔值,甚至没有索引。使用任何其他字段具有相同的效果。现在,如果我要替换另一种类型的项目40 - 我知道有很多记录 - 对于记录较少的类型,索引再次正常工作。
EXPLAIN SELECT item.itemid, item.`type`,item.dir FROM item WHERE item.`type` IN (1,2);
1 SIMPLE item range type type 2 79812 Using index condition
我意识到MySQL的优化器并不完美,但似乎这些额外的数据不应该使逻辑有所不同。
这几乎就像存在某种内存问题,而附加数据不允许MySQL留下足够的内存来完成它的工作。
非常感谢任何想法。
答案 0 :(得分:0)
MySQL的行为合理 - 可能不是最佳,但合理。
当遇到您的一个查询时,优化器基本上有两种选择。
首先,它可以扫描索引以查找相关记录。然后它可能需要在数据页面中查找其他列(dir
也是如此,itemid
也可能如此,这取决于它是否被声明为主索引。)
其次,它可以扫描数据页,应用where
子句并直接从数据页中提取所需的数据。
在进行索引扫描然后查找数据页中的信息与简单地扫描数据页之间的平衡是微妙的。查询中的细微差别可能使一个优先于另一个。
您可以通过创建覆盖索引来强制使用索引。这样的索引包含查询的所有列。对于这些查询,这将是type, itemid, dir
。