1

假设 TABLE1 中有 100 万个条目。

表 2 中有 50k 个条目。

SELECT stringVal 
FROM TABLE2 
WHERE idTable2=5

选择结果:

5
4

该选择需要0.02s处理但是当我在 IN 中使用它时,它最多需要20.20s

SELECT count(*) 
FROM TABLE1 
WHERE stringVal IN (
   SELECT stringVal FROM TABLE2 where idTable2=5);

如果我像这样使用它,它将在 0.02 秒内处理

SELECT count(*) 
FROM TABLE1 
WHERE stringVal IN (5,4);

谁能解释一下这里的工作原理?

4

4 回答 4

3

我认为您的 RDBMS 在执行查询方面做得很差,其他 RDBMS(例如 SQL Server)可以看到,如果子查询与外部查询不相关,它将在内部实现结果并且不会重复执行子查询。例如

select *
    , (select count(*) from tbl) -- an smart RDBMS won't execute this repeatedly
from tbl

一个好的 RDBMS 不会重复执行计数,因为它是一个独立的查询(与外部查询不相关)

尝试所有选项,反正只有少数几个

第一,尝试存在。您的 RDBMS 的 EXISTS可能比它的 IN 快。我遇到的 IN 比 EXISTS 快,例如:为什么最自然的查询(即使用 INNER JOIN(而不是 LEFT JOIN))非常慢 Quassnoi 的相同观察(IN 比 EXISTS 快):http ://explainextended.com /2009/06/16/in-vs-join-vs-exists/

SELECT count(*) 
FROM TABLE1 
WHERE 
   -- stringVal IN 
   EXISTS(
       SELECT * -- please, don't bikeshed ;-)
       FROM TABLE2            
       where 
             table1.stringVal = table2.stringVal -- simulated IN
             and table2.idTable2 = 5);

2nd,尝试 INNER JOIN,如果没有重复就使用这个,或者使用 DISTINCT 删除重复。

SELECT count(*) 
FROM TABLE1 
JOIN (
       SELECT DISTINCT stringVal -- remove duplicates
       FROM TABLE2            
       where table2.idTable2 = 5 ) as x
ON X.stringVal = table1.stringVal

第三,尝试自己实现行。我在使用 SQL Server 时遇到了同样的问题,查询物化行比查询另一个查询的结果要快。

检查将查询结果具体化到表的示例,然后在结果上使用 IN。我发现它比在另一种查询方法上使用 IN 更快,您可以阅读帖子的底部:http ://www.ienablemuch.com/2012/05/recursive-cte-is-evil-and-cursor -is.html

例子:

SELECT distinct stringVal -- remove duplicates
into anotherTable
FROM TABLE2            
where idTable2 = 5;

SELECT count(*) 
FROM TABLE1 where stringVal in (select stringVal from anotherTable);

以上适用于 Sql Server 和 Postgresql,在其他 RDBMS 上可能是这样的:

create table anotherTable as
SELECT distinct stringVal -- remove duplicates
FROM TABLE2            
where table2.idTable2 = 5;


select count(*)
from table1 where stringVal in (select stringVal from anotherTable)
于 2012-06-13T09:47:26.040 回答
1

虽然我喜欢子查询,但它们非常强大,但速度也很慢,因为每次迭代都必须对查询进行完全评估,哎呀!(取决于实施)

这就是为什么他们是我的/我们最后的手段。

一些 SQL 实现非常好,并且会缓存子查询,尽管我不太确定这有多安全,但你仍然必须遍历整个结构,如果结构没有正确优化,如果你嵌套它会花费二次甚至三次时间够了……

SELECT stringVal 
FROM TABLE2 
WHERE idTable2=5

这是线性时间 O(n),如果 sql 数据库存储统计信息,它甚至可以是常数 O(1),但我们假设它不是这样,它将搜索每一行并返回所有匹配 where条款。

SELECT count(*) 
FROM TABLE1 
WHERE stringVal IN (
   SELECT stringVal FROM TABLE2 where idTable2=5);

假设子查询不是缓存,那么它在每一行都被评估,如果你有很多评估,很多浪费的重复计算,即使它的缓存结构可能不是最佳的搜索,不是提到您还在字符串列表中比较字符串。

SELECT count(*) 
FROM TABLE1  
WHERE stringVal IN (5,4);

子查询仍在评估中,但它是一个常量表达式,基本上没有开销,它不需要做任何 IO 或处理锁或任何事情 :)

于 2012-06-13T08:50:37.550 回答
0

试试这个

SELECT count(*) FROM TABLE1 where EXISTS
(SELECT 1 FROM TABLE2 where idTable2=5 and stringVal = TABLE1.stringVal  );

您应该为 TABLE1 和 TABLE2 表的 stringVal 创建索引。

于 2012-06-13T08:45:54.647 回答
0

这是一个简单的连接,它将为您提供与您正在寻找的相同类型的结果。这可以应用于许多不同的情况,这将避免必须查询另一个表。

SELECT COUNT(*)
FROM TABLE1 INNER JOIN TABLE2 ON TABLE1.'COLUMN' = TABLE2.'COLUMN' AND TABLE2.IDTABLE2=5 
WHERE 'WHATEVER YOU WANT'

将“COLUMN”替换为两个表中都引用的列,通常是 ID 或主键。

于 2012-11-14T21:35:33.540 回答