使用 CTE 在 Group by 之前或之后过滤
Filter before Group by or after with CTE
假设我有一个问题:
SELECT SUM(Data1), SUM(Data2), UserID
FROM Table1
WHERE Data1 IN (1, 2, 3)
AND USERID IN (SELECT USERID IN SOME SMALLISH Table of ~10000 Values)
GROUP BY UserID
这个查询的性能如何?将其包装在 CTE 中并在 group by 之后过滤掉 USERID 是否更好?它会用 IN 扫描每一行吗?那第一组应该更快吧?
编辑:添加了用户@jarlh
提到的缺失聚合
我会推荐 exists
:
select data1, data2, userid
from table1 t1
where
data1 in (1, 2, 3)
and exists (select 1 from some_smallish_table s where s.userid = t.userid)
group by data1, data2, userid
然后,您要确保在 some_smallish_table(userid)
上有索引,以便子查询快速执行。
我倾向于将查询更改为使用 EXISTS
——尽管我不确定这是否会对 DB2 产生影响(某些数据库的优化器比其他数据库更好):
SELECT SUM(Data1), SUM(Data2), UserID
FROM Table1 t1
WHERE Data1 IN (1, 2, 3) AND
EXISTS (SELECT 1
FROM smallish s
WHERE t2.USERID = t1.USERID
)
GROUP BY UserID;
那么,如果我没理解错的话,你的问题是这个查询是否会执行得更好:
SELECT SUM(Data1), SUM(Data2), UserID
FROM Table1 t1
WHERE Data1 IN (1, 2, 3)
GROUP BY UserID
HAVING EXISTS (SELECT 1
FROM smallish s
WHERE t2.USERID = t1.USERID
);
首先,您可以在您的数据和系统上测试这两个版本。这始终是验证性能问题的最佳方式。
其次,我希望 WHERE
版本更快——而且更快——因为聚合要聚合的行要少得多。
一个例外是数据库是否可以使用索引进行聚合。我希望 IN
排除这种可能性。另一个例外是,如果 EXISTS
/IN
子句真的非常昂贵(比如不涉及索引),那么 运行 每个结果行只有一次 可能 更快。也就是说,这与聚合中的大量数据相平衡。
假设我有一个问题:
SELECT SUM(Data1), SUM(Data2), UserID
FROM Table1
WHERE Data1 IN (1, 2, 3)
AND USERID IN (SELECT USERID IN SOME SMALLISH Table of ~10000 Values)
GROUP BY UserID
这个查询的性能如何?将其包装在 CTE 中并在 group by 之后过滤掉 USERID 是否更好?它会用 IN 扫描每一行吗?那第一组应该更快吧?
编辑:添加了用户@jarlh
提到的缺失聚合我会推荐 exists
:
select data1, data2, userid
from table1 t1
where
data1 in (1, 2, 3)
and exists (select 1 from some_smallish_table s where s.userid = t.userid)
group by data1, data2, userid
然后,您要确保在 some_smallish_table(userid)
上有索引,以便子查询快速执行。
我倾向于将查询更改为使用 EXISTS
——尽管我不确定这是否会对 DB2 产生影响(某些数据库的优化器比其他数据库更好):
SELECT SUM(Data1), SUM(Data2), UserID
FROM Table1 t1
WHERE Data1 IN (1, 2, 3) AND
EXISTS (SELECT 1
FROM smallish s
WHERE t2.USERID = t1.USERID
)
GROUP BY UserID;
那么,如果我没理解错的话,你的问题是这个查询是否会执行得更好:
SELECT SUM(Data1), SUM(Data2), UserID
FROM Table1 t1
WHERE Data1 IN (1, 2, 3)
GROUP BY UserID
HAVING EXISTS (SELECT 1
FROM smallish s
WHERE t2.USERID = t1.USERID
);
首先,您可以在您的数据和系统上测试这两个版本。这始终是验证性能问题的最佳方式。
其次,我希望 WHERE
版本更快——而且更快——因为聚合要聚合的行要少得多。
一个例外是数据库是否可以使用索引进行聚合。我希望 IN
排除这种可能性。另一个例外是,如果 EXISTS
/IN
子句真的非常昂贵(比如不涉及索引),那么 运行 每个结果行只有一次 可能 更快。也就是说,这与聚合中的大量数据相平衡。