IN vs NOT EXISTS 子句,查询优化
Posted
技术标签:
【中文标题】IN vs NOT EXISTS 子句,查询优化【英文标题】:IN vs NOT EXISTS clause, query optimization 【发布时间】:2015-03-03 08:08:14 【问题描述】:以下是示例的简化表格:
这是我的查询:
从文章 A 中选择 *
A.id 在哪里(
从文章 A1、article_tag AT 中选择 AT.article_id
在哪里(A1.id = AT.article_id)
AND (AT.tag_id IN (2,1))
按 AT.article_id 分组
HAVING count(AT.article_id) = 2
);
从技术上讲,这个查询似乎确实有效并返回 "all the articles having at least keywords 2 and 1"
。
粗体部分是为了改变。例如,如果我的关键字列表是 [1, 3, 4],
(2, 1)
将更改为 (1, 3, 4),2
将更改为 3(列表长度)。
虽然这个查询确实有效,但我稍微记得有个朋友使用 NOT EXISTS 子句。适用吗?如果是,哪个查询在性能方面是最好的优化?
【问题讨论】:
子查询中不同的计数! EXISTS 或多或少与 IN 相同,至少在(大多数)dbms 优化之后。 (NOT EXISTS 是 NOT IN 的“空安全”替代方案。) 您也可以在子查询中的两个条件上应用联接,但相同的只是让您在查看时清楚。 【参考方案1】:您不需要 EXISTS 或 IN - 只需 GROUP BY
文章中的所有列,您就完成了。示例(在 Oracle 语法中,因为您没有提及您的 RDBMS):
with article(id, title) as (
select 1, 'MS SQL Server' from dual union all
select 2, 'Oracle' from dual union all
select 3, 'PostgreSQL' from dual union all
select 4, 'IDBM DB2' from dual),
article_tag(id, article_id, tag_id) as (
select 1,1,1 from dual union all
select 2,1,2 from dual union all
select 3,2,1 from dual union all
select 4,3,2 from dual
)
SELECT a.id, a.title
FROM article a
JOIN article_tag at ON a.id = at.article_id
AND at.tag_id IN (2,1)
GROUP BY a.id, a.title
HAVING COUNT(at.article_id) = 2;
【讨论】:
【参考方案2】:如果是,哪个查询在性能方面是最好的优化?
在优化 sql 时,您唯一的朋友就是查询计划和启用统计信息。结果通常取决于表中的数据。在查询计划中,您可以查看 sql-server 对某些表的操作,并通过统计信息查看原始计时和读取。
查看查询时,您可以进行 INNER JOIN、EXISTS、IN、TABLE VALUED FUNCTION、INLINE TABLE VALUED FUNCTION 等。在许多情况下,sql server 会将它们优化为相同的查询计划。但是在某些情况下它不会。首先进行查询并查看需要哪些索引,在许多情况下,索引比您编写查询的方式更重要。
优化sql查询的关键是使用真实数据和真实参数。然后测量、测量、测量和分析 IO/Reads/Timings 等。
【讨论】:
我很好奇 - 是什么告诉你 OP 正在使用 SQL 服务器?【参考方案3】:我可以看到的一个问题是数据库将无法重用查询计划,因为对于不同的参数,您正在更改查询文本。这通常会导致次优查询计划。
因此,与其考虑 in
与 exists
,不如考虑将选项作为参数传递。你没有指定你正在使用什么数据库引擎,所以我不能说任何具体的事情。例如,在 MS SQL 上,您可以使用表参数或xml
参数来执行此操作,帮助查询规划器完成其工作。
您还可以使用一些技巧来使查询更直接,但您应该只对查询的使用方式和执行方式的具体统计信息进行此类操作。
警惕轶事证据 - 很多反对使用 in (subquery)
和类似的论点已经存在多年,不再需要适用于您的场景。措施。准备真实的测试数据。措施。猜测很痛苦:)
【讨论】:
以上是关于IN vs NOT EXISTS 子句,查询优化的主要内容,如果未能解决你的问题,请参考以下文章
AS3 - for (... in ...) vs for each (... in ...)
Where is NuGet in VS2017 Community?
structure vs class in swift language