由于选择性较低,MariaDB不对1列自连接使用索引(所有NULL)

时间:2015-12-05 11:13:08

标签: mysql indexing innodb mariadb

我们有一个查询在我们的一个表中查找重复项,基于很少可用的标识符,我们称之为rareIdentifier INT(10) UNSIGNED NULL。我们在此列上有一个单列常规旧索引。

有问题的查询如下所示:

SELECT a.id, b.id FROM
    widget a INNER JOIN widget b
ON a.rareIdentifier = b.rareIdentifier;

问题是,对于最近的重复查找运行,我们实际上有0行,其值为rareIdentifier;即此列的所有行都有NULL。 MariaDB决定不使用索引,选择扫描整个表格的Using join buffer (flat, BNL join)方法。

但是NULL s不能相等!那么为什么要尝试比较每对行呢?

据我所知,如果MySQL / MariaDB的选择性太低,它将不会使用索引。我相信这就是这种情况。事实上,似乎只在索引中有一个值意味着查询几乎是即时的。

该表是InnoDB表。

2 个答案:

答案 0 :(得分:0)

InnoDB可能不够智能,因为与NULL相比总是NULL,因此是假的。也许它只是决定"所有值都是相同的,所以它们必须相等" (但实际上我真的不知道)。

作为一种解决方法,添加... AND a.rareIdentifier IS NOT NULL应该为优化程序提供足够的提示。

答案 1 :(得分:0)

在大多数情况下,这可能会更快,特别是如果有许多行具有相同的rareIdentifier

SELECT  rareIdentifier, MIN(id), MAX(id), COUNT(*)
    FROM tbl
    WHERE rareIdentifier IS NOT NULL
    GROUP BY rareIdentifier
    HAVING COUNT(*) > 1;

或者您可以使用GROUP_CONCAT(id)代替min&最大。 (但是,如果有很多重复,则列表将被截断。)

假设InnoDB和INDEX(rareIdentifier),这个SELECT应该是一个非常有效的范围'扫描索引。

回到你的问题......

  

实际上有0行...... MariaDB决定不使用索引

我曾经在旧版本的MySQL中看到很多东西。我想知道Oracle是否已修复,但MariaDB错过了修复程序。