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

Tom*_*man 10 sql sql-server performance

我有两张桌子.表单有~77000行.日志有大约270万行.

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

SELECT COUNT(DISTINCT logs.DOCID) FROM logs, forms WHERE logs.DOCID = forms.DOCID;
Run Code Online (Sandbox Code Playgroud)

此查询到目前为止已运行约15分钟,但仍未完成:

SELECT COUNT(DISTINCT logs.DOCID) FROM logs, forms WHERE logs.DOCID <> forms.DOCID;
Run Code Online (Sandbox Code Playgroud)

为什么是"不等于"查询这么慢得多?

Mar*_*c B 28

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

想一想 - 你和5个男孩和5个女孩一起跳舞:

Adam      Alice
Bob       Betty
Charly    Cathy
Dick      Deb
Evan      Elly
Run Code Online (Sandbox Code Playgroud)

你用第一个字母将它们配对.所以

Adam->Alice
Bob->Betty
etc...
Run Code Online (Sandbox Code Playgroud)

一对配对

但是,如果你通过"首字母不匹配"将它们配对,你最终得到:

Adam->Betty
Adam->Cathy
Adam->Deb
Adam->Elly
Bob->Alice
etc...
Run Code Online (Sandbox Code Playgroud)

你已经大量增加了配对次数.这就是您的<>查询花了这么长时间的原因.你本质上是在尝试获取m x n行,而不仅仅是min(m,n).使用这些数据,最终会得到25行,而不是5行.对于指定的表格大小,您使用的是77,000*2,700,000 = 207.9亿行,减去77,000,其中两个ID匹配,总共207,899,923,000行连接的数据集.


根据您的查询要求,尝试左连接并查找空的右侧记录:

SELECT DISTINCT logs.DOCID
FROM logs
LEFT JOIN forms ON logs.DOCID = forms.DOCID
WHERE forms.DOCID IS NULL
Run Code Online (Sandbox Code Playgroud)

  • +1我猜测OP可能需要`NOT IN`或`NOT EXISTS`或`EXCEPT` (2认同)