我有两个表。窗体有~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)
,并且只有一行具有不同的值,那么您将看到完全相反的行为。