[有人可以帮助我重写查询以加快执行时间吗?花费了[[37秒的时间。
DELETE FROM storefront_categories
WHERE userid IN (SELECT userid
FROM MASTER
where expirydate<'2020-2-4'
)
同时,此查询只花了4.69秒即可执行。
DELETE FROM storefront_categories WHERE userid NOT IN (SELECT userid FROM MASTER)
表具有97K条记录,而MASTER中具有40K条记录。我们已经在MASTER.expirydate字段上创建了一个索引。storefront_categories
我建议以下索引进行优化:
master(expiry_date, userid)
storefront_categories(userid)
第一个索引是master
上子查询的covering索引:这意味着数据库应该仅通过查看索引即可执行子查询(而索引中只有
第二个索引使数据库优化expiry_date
,它仍然需要查看表数据以获取相关的userid
)。in
操作。
exists
:DELETE
FROM storefront_categories
WHERE EXISTS (SELECT 1
FROM MASTER M
WHERE M.userid = storefront_categories.userid AND
M.expirydate <'2020-02-04'
);
索引将在这里出现,我希望索引在storefront_categories(userid) & MASTER(userid, expirydate)
上。
NOT EXISTS
与正确的索引一起使用:DELETE sc
FROM storefront_categories sc
WHERE NOT EXISTS (SELECT 1
FROM master m
WHERE m.userid = sc.userid AND
m.expirydate < '2020-02-04'
);
您想要的索引在master(userid, expirydate)
上。列的顺序很重要。对于此版本,storefront_categories
上的索引无济于事。注意,我更改了日期格式。我建议使用YYYY-MM-DD以避免歧义-并使用完整的10个字符。
删除表的40%时,将要复制的行保存到另一个表然后交换表要快得多。
[删除大量行时(无论百分比如何),最好分块执行。最好根据PRIMARY KEY
浏览表格。
我在http://mysql.rjweb.org/doc.php/deletebig中讨论了这两种技术以及其他技术>
关于查询表述:
NOT IN (SELECT ...)
和NOT EXISTS
往往表现最差。IN (SELECT ...)
和/或EXISTS
可能更好。DELETE
是另一个选项。它的作用类似于JOIN
。