根据某些标准,我必须从具有超过 1 亿行的表中删除大约 10K 行。当我执行查询时,大约需要 5 分钟。我运行了一个解释计划(delete
查询转换为select *
MySQL 不支持explain delete
),发现 MySQL 使用了错误的索引。
我的问题是:有没有办法告诉 MySQL 在删除期间使用哪个索引?如果没有,我该怎么办?选择临时表然后从临时表中删除?
根据某些标准,我必须从具有超过 1 亿行的表中删除大约 10K 行。当我执行查询时,大约需要 5 分钟。我运行了一个解释计划(delete
查询转换为select *
MySQL 不支持explain delete
),发现 MySQL 使用了错误的索引。
我的问题是:有没有办法告诉 MySQL 在删除期间使用哪个索引?如果没有,我该怎么办?选择临时表然后从临时表中删除?
有索引提示语法。//ETA: sadly, not for deletes
ETA:你试过跑步ANALYZE TABLE $mytable
吗?
如果这没有得到回报,我认为您有 2 个选择:在删除之前删除有问题的索引并在之后重新创建它。或者将您的删除表加入所需索引上的另一个表,这应确保使用所需的索引。
我从来没有真正遇到过 MySQL 选择错误索引的情况,而是我对索引如何工作的理解通常是错误的。
你可能想看看这本书:http: //oreilly.com/catalog/9780596003067
它有一个关于索引如何工作和其他调整选项的精彩部分。
如其他答案所述,MySQL 不能使用索引,而是 PRIMARY KEY 索引。
所以你最好的选择,如果你在表上有一个主键是运行一个快速的选择,然后根据行删除。最好在 TRANSACTION 中,这样您就不会删除错误的行。
因此:
DELETE FROM table WHERE column_with_index = 0
将被重写:
SELECT primary_key FROM table WHERE column_with_index = 0
=> 返回多行
DELETE FROM table WHERE primary_key IN(?, ?, ?)
=>?
将被 SELECTed 主键的结果替换。
如果您没有太多要删除的行,那么这种方式会更有效。
例如,我刚刚在同一张桌子上用相同的数据打了一个例子:
对比