【问题标题】:mariadb non selective index on foreign keys外键上的 mariadb 非选择性索引
【发布时间】:2018-10-11 21:02:54
【问题描述】:

我正在对 mariaDB 上一个非常慢的索引进行故障排除。它需要 10 多秒。 该表有超过 10M 行。 where 子句有'where a=x and b=y'。 b 列具有选择性索引。 列 a 具有非选择性索引(只有 5 个不同的值),但它不能被删除,因为 a 是外键。 mariaDB 使用了两个索引的交集,这使得它的性能比单独使用 b 上的索引差很多。 我不知道如何解决这个问题:

  • 我无法删除 a 上的索引,因为我想确保完整性
  • 我不想取消整个数据库的相交索引优化
  • 我不想使用索引提示,因为它不是标准的(即使我不确定我还有什么其他选项)。

有什么想法吗?

【问题讨论】:

  • 我们需要相关表格的SHOW CREATE TABLE 的输出。也许您的计算机着火了并且 CPU 受到了限制,或者它正在使用 5400 RPM 驱动器,我们不知道这里会发生什么。 “它很慢”是一种观察结果,而不是我们可以使用的诊断方法。
  • 感谢 tadman,我在下面添加了一些输出。然而问题是一般性的:一个外键自动添加一个索引,这个索引可以是非选择性的(这通常是父表的情况),然后优化器使用 intersect 如果索引之一是非选择性的,这会损害性能。
  • 值得编辑问题并以正确的格式添加该内容。它在 cmets 中表现不佳。
  • 您是否已经在表上尝试过复合索引?

标签: mysql sql query-optimization mariadb query-performance


【解决方案1】:

外键自动添加索引...

嗯...在 MariaDB 中,是的。无论如何,这都不是标准功能;其他数据库(Oracle、DB2、PostgreSQL 等)不会自动创建索引来强制执行外键。

我无法完全理解您的问题,但在我看来您有两个索引,一个使用列 a,另一个使用列 b。而且...您正在尝试决定使用哪一个或如何组合它们。

使您提到的查询使用索引并不难。如果 WHERE 条件是 where a=x and b=y,这是一个完美的案例,可以通过创建索引 (b, a) 来大幅加速,如下所示:

create index ux_mytable_b_a on my_table (b, a);

注意我使用了(b, a) 而不是(a, b)。这样最有选择性的列被放置在最前面,并且查询运行的哈希冲突和/或存储桶溢出的机会更少。

现在,关于您的观察:

mariaDB 使用 2 个索引的交集,这使其性能更差...

请注意,组合第三个​​索引(包含两列)可避免索引交集。 MariaDB 会自动选择新的索引,因为它比使用以前的任何组合都快。

【讨论】:

  • 谢谢。事实上,我最终添加了一个组合索引。只是为了澄清情况:在 mysql 和 mariadb 中,外键会自动创建索引。此类索引通常是非选择性的。但是没有办法删除它们(并保留外键)或禁用它们作为优化器的可能键。这会导致优化器与非选择性索引进行交集,与使用单个选择性索引相比,其性能较差。
  • MariaDB 不使用散列或桶。无论个人基数如何,(b,a)(a,b) 都一样好。
  • @ItamarTayer - 如果你已经有INDEX(a,b) 并添加FOREIGN KEY ... REFERENCES ... a ...,它应该说复合索引就足够了。
  • @RickJames 点已被占用。 MariaDB 不使用哈希表。不过b,aa,b 快,因为ba 更具选择性。也就是说,与首先按a 过滤相比,首先按b 值过滤会大大减少候选行。
  • @TheImpaler - 但它没有过滤一个,然后是另一个。它通过在 BTree 中使用 single 向下钻取来过滤组合。这相当于连接两列,然后在该组合列上有一个索引。
猜你喜欢
  • 2013-09-15
  • 2012-10-25
  • 1970-01-01
  • 1970-01-01
  • 2014-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-10
相关资源
最近更新 更多