我正在查看一个应用程序,我发现这个SQL:
DELETE FROM Phrase
WHERE PhraseId NOT IN(SELECT Id FROM PhraseSource)SQL的目的是从不位于PhraseSource表中的短语中删除行。
这两个表是相同的,具有以下结构
Id - GUID primary key
...
...
...
Modified int...列大约有十个列,包含文本和数字数据。PhraseSource表可能包含也可能不包含修改后的列中数字较高的最近行以及不同的文本和数字数据。
有人能告诉我,这个查询会对短语表中的每一行执行SELECT Id PhraseSource吗?如果是这样的话,是否有一种更有效的方法来对其进行编码。
发布于 2016-11-16 07:39:57
在这种情况下,如果数据库系统不够聪明,可以为每一行计算子查询(但对于MS SQL Server,我认为它应该能够识别这样一个事实,即您不需要对子查询进行多次计算)。
还有一个更好的解决办法:
DELETE p
FROM Phrase p
LEFT JOIN PhraseSource ps ON ps.Id = p.PhraseId
WHERE ps.Id IS NULL这使用了与两个表的行相匹配的LEFT JOIN,但如果没有匹配,则会留下ps条目NULL。现在,您只需检查左侧的NULLs,以查看哪个Phrases没有匹配,并将删除它们。
所有类型的JOIN语句都是很好的在这个答案中描述。
在这里你可以看到针对类似问题的三种不同方法在MySQL上进行了比较。正如@Drammy所提到的,要实际查看给定方法的性能,您可以在目标数据库上看到执行计划,并在相同问题的不同方法上进行性能测试。
发布于 2016-11-16 07:44:55
该查询应该优化为一个联接。你看过执行计划了吗?
如果您的性能不佳,很可能是因为guid主键。
默认情况下,主键是群集的。如果guid主键聚集在您的表上,这意味着表中的数据由主键排序。guids作为集群键的问题是,当您删除一条记录时,必须对表进行重新排序,并在磁盘上来回移动。
这篇文章对这个题目读得很好。
https://blog.codinghorror.com/primary-keys-ids-versus-guids/
https://stackoverflow.com/questions/40626383
复制相似问题