我实际上正在努力理解这里的问题。我到处读到说 UPDATE 受益于 WHERE 子句上的索引。
但是,这个查询,
UPDATE `documents` SET `read`="1" WHERE `docid` IN (<subquery>)
似乎没有使用索引。该表documents
有一个索引 ondocid
和 on read
。
当我执行 时EXPLAIN
,我看到possible_keys = NULL
和rows = 8011008
(全表)。子查询确实使用键并读取正确的行(2 行)。
另一方面,这个查询:
SELECT * FROM `documents` WHERE `docid` IN (<subquery>)
确实使用索引docid
并且运行速度非常快。它读取的行数比需要的多(根据EXPLAIN
),但完全可以接受。
对此有什么解释吗?
我使用 MariaDB 10。
作为一个有趣的注释(关于SELECT
),如果在<subquery>
我使用 aUNION
时,子查询似乎获得了正确的行数,但似乎主查询不使用索引并进行全表扫描。
如果在UPDATE
I 中使用JOIN
而不是IN
,则正确使用索引。我通过使用解决了我的问题JOIN
。
为了解决“UPDATE 不使用 INDEX,但 SELECT 使用”的问题...
直到最近,许多
UPDATEs
都是由不同的代码处理的SELECTs
。最近,Oracle 分支进行了统一。我认为它还没有进入 MariaDB。此外,在
IN ( SELECT ... )
5.6 之前,该结构的优化非常差。同样,MariaDB 可能包含也可能尚未包含该领域的一些 5.6/5.7 改进。... IN ( SELECT ... )
变成几乎总是更好JOIN ... ON ...
。这在UPDATE
; 请参阅“多表更新”。有关您的具体案例的更多讨论,请提供
SHOW CREATE TABLE
和EXPLAIN SELECT ...
。我并不是说 Oracle 分支一定会做得更好。而是可能存在差异。