UPDATE不使用INDEX,但SELECT使用

Nun*_*uno 3 mysql innodb mariadb index mariadb-10.1

我实际上很难理解这里的问题。我到处都看到说 UPDATE 受益于 WHERE 子句上的索引。

然而,这个查询,

UPDATE `documents` SET `read`="1" WHERE `docid` IN (<subquery>)
Run Code Online (Sandbox Code Playgroud)

似乎没有使用索引。该表documents有一个索引 ondocid和 on read

当我执行 时EXPLAIN,我看到possible_keys = NULLrows = 8011008(全表)。子查询确实使用键并读取正确的行(2 行)。

另一方面,这个查询:

SELECT * FROM `documents` WHERE `docid` IN (<subquery>)
Run Code Online (Sandbox Code Playgroud)

确实使用索引docid并且运行速度非常快。它读取的行数比需要的多(根据EXPLAIN),但完全可以接受。

对此有什么解释吗?
我使用 MariaDB 10。

作为一个有趣的注释(关于SELECT),如果在<subquery>我使用 aUNION时,虽然子查询似乎获得了正确的行数,但主查询似乎不使用索引并进行全表扫描。

如果在UPDATEI useJOIN而不是 中IN,则索引被正确使用。我通过使用解决了我的问题JOIN

Ric*_*mes 5

为了解决“UPDATE 不使用 INDEX,但 SELECT 却使用”这个问题......

直到最近,许多UPDATEs都是由与SELECTs. 最近,Oracle分支进行了统一。我认为它还没有进入 MariaDB。

此外,IN ( SELECT ... )在 5.6 之前,该结构的优化非常差。同样,MariaDB 可能已包含也可能尚未包含该领域的一些 5.6/5.7 改进。

... IN ( SELECT ... )变成几乎总是更好JOIN ... ON ...。这是可能的UPDATE;请参阅“多表更新”。

如需对您的具体案例进行更多讨论,请提供SHOW CREATE TABLEEXPLAIN SELECT ...

我并不是说 Oracle 分支一定会做得更好;而是说 Oracle 分支一定会做得更好。相反,可能存在差异。