为什么MySQL DELETE无法在子查询上使用索引?

时间:2016-07-28 16:16:47

标签: mysql select subquery mariadb sql-delete

正如在other questions中所建立的那样,使用"子查询"在MySQL中删除会导致它变慢,而相同的"选择"查询执行速度快:

MariaDB [as_01_import]> explain select * from invoice_payment where invoice_id in (select id from dochead where system_id = 5786);
+------+-------------+-----------------+------+---------------------------------------+----------------------------+---------+-------------------------+------+-------------+
| id   | select_type | table           | type | possible_keys                         | key                        | key_len | ref                     | rows | Extra       |
+------+-------------+-----------------+------+---------------------------------------+----------------------------+---------+-------------------------+------+-------------+
|    1 | PRIMARY     | dochead         | ref  | PRIMARY,dochead_system_id             | dochead_system_id          | 4       | const                   |  891 | Using index |
|    1 | PRIMARY     | invoice_payment | ref  | invoice_payment_invoice_fk,invoice_id | invoice_payment_invoice_fk | 4       | as_01_import.dochead.id |    1 |             |
+------+-------------+-----------------+------+---------------------------------------+----------------------------+---------+-------------------------+------+-------------+


MariaDB [as_01_import]> explain delete from invoice_payment where invoice_id in (select id from dochead where system_id = 5786);
+------+--------------------+-----------------+-----------------+---------------------------+---------+---------+------+---------+-------------+
| id   | select_type        | table           | type            | possible_keys             | key     | key_len | ref  | rows    | Extra       |
+------+--------------------+-----------------+-----------------+---------------------------+---------+---------+------+---------+-------------+
|    1 | PRIMARY            | invoice_payment | ALL             | NULL                      | NULL    | NULL    | NULL | 1235451 | Using where |
|    2 | DEPENDENT SUBQUERY | dochead         | unique_subquery | PRIMARY,dochead_system_id | PRIMARY | 4       | func |       1 | Using where |
+------+--------------------+-----------------+-----------------+---------------------------+---------+---------+------+---------+-------------+
2 rows in set (0.44 sec)

知道JOIN可以使用索引,我想问专家:

什么阻止MySQL / MariaDB在DELETE中使用SUBQUERY中的索引?这是一个实现问题还是存在概念问题?有没有计划解决这个问题?影响其他SQL供应商的问题是否相同?

2 个答案:

答案 0 :(得分:2)

子查询是派生表,未实现。它们表现在临时表中。

正如我在this answer写的那样:

  

文档Derived Tables in MySQL 5.7很好地描述了它   版本5.6和5.7,后者将不提供任何惩罚   物化衍生表输出的变化被合并   进入外部查询。在以前的版本中,大量的开销是   使用派生的临时表忍受。

答案 1 :(得分:1)

请勿使用IN ( SELECT ... )。相反,请使用此处所述的多表DELETEhttp://dev.mysql.com/doc/refman/5.5/en/delete.html

这样做会在适用的情况下使用索引。