Mysql 外键上的非选择性索引
我正在对mariaDB上的一个非常慢的索引进行故障排除。它需要超过10秒。 这张桌子有超过10万行。 where子句具有“where a=x和b=y”。 b列有一个选择性索引。 列a有一个非选择性索引(只有5个不同的值),但不能删除,因为a是外键。 mariaDB使用了两个索引的交集,这使得它的性能比单独在b上使用索引要差得多。 我不知道如何解决这个问题,因为:Mysql 外键上的非选择性索引,mysql,sql,query-optimization,mariadb,query-performance,Mysql,Sql,Query Optimization,Mariadb,Query Performance,我正在对mariaDB上的一个非常慢的索引进行故障排除。它需要超过10秒。 这张桌子有超过10万行。 where子句具有“where a=x和b=y”。 b列有一个选择性索引。 列a有一个非选择性索引(只有5个不同的值),但不能删除,因为a是外键。 mariaDB使用了两个索引的交集,这使得它的性能比单独在b上使用索引要差得多。 我不知道如何解决这个问题,因为: 我无法删除上的索引,因为我希望确保完整性 我不想取消整个数据库的交叉索引优化 我不想使用索引提示,因为它不是标准的(尽管我不确定还有
- 我无法删除上的索引,因为我希望确保完整性
- 我不想取消整个数据库的交叉索引优化
- 我不想使用索引提示,因为它不是标准的(尽管我不确定还有什么其他选项)
a
,另一个使用列b
。而且。。。您正在尝试决定使用哪一个或如何组合它们
让您提到的查询使用索引并不困难。如果WHERE条件是a=x和b=y,则这是一个通过创建索引(b,a)
来大幅加速的完美情况,如下所示:
create index ux_mytable_b_a on my_table (b, a);
注:我使用了(b,a)
,而不是(a,b)
。这样,最有选择性的列被放在第一位,查询运行哈希冲突和/或bucket溢出的可能性更小
现在,关于你的观察:
mariaDB正在使用两个索引的交集,这使得它的性能更差
请注意,合并第三个索引(有两列)可以避免索引交叉。MariaDB将自动选择新索引,因为它比使用以前索引的任何组合都要快。我们需要相关表的
SHOW CREATE TABLE
输出。也许你的电脑着火了,CPU被限制了,或者它使用了5400 RPM的驱动器,我们不知道这里会发生什么。“它很慢”是一种观察,而不是我们可以使用的诊断。谢谢tadman,我在下面添加了一些输出。但问题是一般性的:foreing键会自动添加一个索引,该索引可能是非选择性的(对于父表来说通常是这样),然后优化器会使用intersect,如果其中一个索引是非选择性的,则会损害性能。编辑该问题并添加具有正确格式的内容是值得的。它在注释中显示得不好。您已经在表上尝试过复合索引了吗?谢谢。事实上,我最终添加了一个组合索引。澄清一下情况:在mysql和mariadb中,外键自动创建索引。这类指数通常是非选择性的。但是,没有办法删除它们(并保留外键)或禁用它们作为优化器的可能键。这会导致优化器与非选择性索引相交,与使用单个选择性索引相比,非选择性索引的性能较差。MariaDB不使用哈希或桶(b,a)
和(a,b)
同样好,不管它们各自的基数是多少。@ItamarTayer-如果您已经有索引(a,b)
并添加外键。。。参考资料。。。a…
,应该说复合索引就足够了。MariaDB不使用哈希表。然而b,a
比a,b
快,因为b
比a
更具选择性。也就是说,与先按a
过滤相比,先按b
值过滤会大大减少候选行数。@theimpler-但它不是先过滤一行,然后过滤另一行。它通过在BTree中使用单个向下钻取来过滤组合。这相当于将两个列连接起来,然后在组合的列上有一个索引。