与表上的"="相比,SQL Server "<>"运算符非常慢,只有几百万行



我有两个表。窗体有~77000行。日志有~ 270万行。

下面的查询在不到一秒的时间内返回"30198":

SELECT COUNT(DISTINCT logs.DOCID) FROM logs, forms WHERE logs.DOCID = forms.DOCID;

到目前为止,这个查询已经运行了大约15分钟,仍然没有完成:

SELECT COUNT(DISTINCT logs.DOCID) FROM logs, forms WHERE logs.DOCID <> forms.DOCID;

为什么"not equal"查询所以要慢得多?

因为=将连接操作减少到每个表中的单个匹配行(假设这些docid是唯一的)。

这样想——你有5个男孩和5个女孩跳舞:

Adam      Alice
Bob       Betty
Charly    Cathy
Dick      Deb
Evan      Elly

按首字母配对。所以

Adam->Alice
Bob->Betty
etc...

单对

但是如果你用"首字母不匹配"来配对它们,你就会得到:

Adam->Betty
Adam->Cathy
Adam->Deb
Adam->Elly
Bob->Alice
etc...

你已经大量增加了配对的数量。这就是为什么您的<>查询需要这么长时间。你实际上是在尝试获取m x n行,而不仅仅是min(m,n)行。有了这些数据,最终得到25行,而不是5行。对于指定的表大小,您将使用77,000 * 2,700,000 = 2079亿行,减去两个id匹配的77,000行,在连接的数据集中总共有207,899,923,000行。


给定您的查询要求,尝试左连接并查找null右侧记录:

SELECT DISTINCT logs.DOCID
FROM logs
LEFT JOIN forms ON logs.DOCID = forms.DOCID
WHERE forms.DOCID IS NULL

两个原因:

  • 对于等价性的查询一般可以使用索引(如果可用),而对于非等价性的查询不能

  • <>返回更多数据

你对<>的查询是假的。它应该返回什么?

这完全取决于表中值的分布。例如,如果您正在搜索的列对于99.99%的行具有相同的值(= forms.DOCID),并且只有一行具有不同的值,那么您将看到完全相反的行为。

最新更新