mysql如何使用多字段索引来查询中间的索引字段?

e7arh2l6  于 2021-06-20  发布在  Mysql
关注(0)|答案(2)|浏览(274)

我有具有多列非唯一索引的innodb表项(group\u id、type\u id、expiry\u date)。
如有疑问 SELECT * FROM Items WHERE group_id = 1 AND type_id IN (1,2,3) AND expiry_date BETWEEN '2017-01-01' AND '2018-01-01' 索引会像我使用的那样正常工作吗 IN 对于第二个领域的索引和他们额外有范围的第三将或我应该受益于吐它到? SELECT * FROM Items WHERE group_id = 1 AND type_id = 1 AND expiry_date BETWEEN '2017-01-01' AND '2018-01-01' UNION SELECT * FROM Items WHERE group_id = 1 AND type_id = 2 AND expiry_date BETWEEN '2017-01-01' AND '2018-01-01' UNION SELECT * FROM Items WHERE group_id = 1 AND type_id = 3 AND expiry_date BETWEEN '2017-01-01' AND '2018-01-01' explain为两个查询显示了相同的查询计划,但我有一个非常小的表用于测试,不确定查询优化程序是否会对大量数据执行相同的操作。
一般来说,索引是如何使用case的 IN/OR/BETWEEN 关于索引中的2个结果域?

bz4sfanl

bz4sfanl1#

对于第二个查询,使用 union all 而不是 union . 你总是想要 union all ,除非您希望在删除重复项时产生开销。
我猜你会从第二个关于更大数据的查询中受益。我不认为mysql支持跳过索引扫描,所以索引只用于 group_id 以及 type_id ,但不能直接用于日期。

cczfrluj

cczfrluj2#

什么版本的mysql/mariadb?最近进行了优化;如果他们愿意帮忙,现在就不要。
你有一个可能的错误——包括在 AND expiry_date BETWEEN '2017-01-01' AND '2018-01-01' . 更改为

AND expiry_date >= '2017-01-01'
AND expiry_date  < '2017-01-01' + INTERVAL 1 YEAR

(这算是一个单一的“范围”测试。 BETWEEN 也是一个范围测试,但它是“包含的”,因此是“bug”。)
我只需要两个综合指数(如果我找不到你问题的真正答案):

(group_id, type_id, expiry_date)
(group_id, expiry_date)

案例1:优化器可以通过 IN :则第一个索引起作用。
情况2:优化器无法通过 IN :然后发生以下情况之一:
这个 IN 列表只有一项。然后从 IN= ,并且第一个索引是最佳的,使用了所有3列。
优化器决定第一个索引更好——列表小,日期范围大。
优化器决定日期范围更好(范围更小),并选择第二个索引。
这个 UNION 在这种情况下,这种方法可能更好,也可能不更好。将数据收集到临时表中会有很多开销。临时表最近被取消了,但只适用于某些特殊情况 UNION ALL .
是的,使用 UNION ALL . 这样就消除了一个排序和一个额外的temp表。
使用大型数据集进行测试。对于1k以下的行,性能可能无关紧要。
索引中列排序的经验法则: = 测试 IN ,如果有的话
一个“范围”( BETWEEN , < 等),如果有的话
考虑做一个“覆盖”索引。
我的食谱
还有其他一些优化取决于 *SELECT * .

相关问题