Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 外键上的非选择性索引_Mysql_Sql_Query Optimization_Mariadb_Query Performance - Fatal编程技术网

Mysql 外键上的非选择性索引

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上使用索引要差得多。 我不知道如何解决这个问题,因为: 我无法删除上的索引,因为我希望确保完整性 我不想取消整个数据库的交叉索引优化 我不想使用索引提示,因为它不是标准的(尽管我不确定还有

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

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

foring键会自动添加索引

嗯。。。在马里亚布,是的。这无论如何都不是一个标准特性;其他数据库(Oracle、DB2、PostgreSQL等)不会自动创建索引来强制执行外键

我不能完全理解你的问题,但在我看来,你有两个索引,一个使用列
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中使用单个向下钻取来过滤组合。这相当于将两个列连接起来,然后在组合的列上有一个索引。