在EXISTS条件下使用= vs IN运算符的性能差异是什么?

时间:2019-06-19 09:27:52

标签: sql-server

在SQL Server中,当使用WHERE EXISTS标准时,使用=与IN运算符之间是否有性能差异?

示例:

SELECT
    customer_id,
    first_name,
    last_name
FROM
    sales.customers c
WHERE
    EXISTS (
        SELECT *
        FROM sales.orders o
        WHERE customer_id = c.customer_id --we can also replace = with IN - for example customer_id IN c.customer_id or say c.customer_id IN customer_id
    )

另一个例子是:

SELECT
    customer_id,
    first_name,
    last_name
FROM
    sales.customers c
WHERE
    EXISTS (
        SELECT *
        FROM #Customers x --say #Customers is temp table containing a couple of customers for which we want to show the output
        WHERE c.customer_id = x.customer_id --we can also replace = with IN - for example c.customer_id IN x.customer_id or say x.customer_id IN c.customer_id
    )

此问题被标记为this的重复项。这个问题是关于。存在与否。而我的问题是使用EXISTS时的re = vs IN

2 个答案:

答案 0 :(得分:2)

没有任何区别。

写作时

WHERE A IN(B)

与写作

完全相同
WHERE A = B

如果AB是一列,则表达式或常量不会改变IN运算符的性质。

如果您要写

WHERE A IN(B, C)

那与写作一样

WHERE A = B OR A = C

此条件是EXISTS运算符内子查询的一部分的事实是不相关的。

答案 1 :(得分:1)

我认为您误解了相关子查询如何与EXISTS一起使用。

均等比较(=)与另一个特定值评估一个特定值,并返回true或false。除非您添加其他逻辑运算符AND / OR,否则它无法评估多个值。 IN运算符只是用OR运算符简化一堆=的方式,因此更容易阅读,如Zohar在另一个答案中所述。

另一方面,EXISTS运算符使用 左半连接 来检查特定记录的存在。每当您要检查特定行是否存在时,就在布尔上下文中使用EXISTS。一旦找到第一行,SQL引擎就会停止搜索匹配的行。这是 左半联接 的目的,也是与 左外联接 的区别之一(不是检索联接表的数据和匹配的行数)。

所以当您写:

FROM
    sales.customers c
WHERE
    EXISTS (
        SELECT *
        FROM sales.orders o
        WHERE o.customer_id = c.customer_id
    )

您正在使用关联的子查询将customersorders链接。子查询在EXISTS运算符的上下文中使用,如果{{中至少有 1行,则将对sales.customers的每一行进行引擎搜索。 1}}满足以下条件:

sales.orders

对于不是来自我们当前正在检查的客户的每个订单,此情况将作为WHERE o.customer_id = c.customer_id 产生。引擎将忽略这些行,因为我们正在寻找存在。仅返回false中具有customers且在子查询中产生一行的行。

如果我们将条件更改为customer_id

IN

子查询将检查满足条件的表FROM sales.customers c WHERE EXISTS ( SELECT * FROM sales.orders o WHERE o.customer_id IN (c.customer_id) ) 上是否存在:

sales.orders

这恰好与我们在WHERE o.customer_id IN (c.customer_id) 示例中引用的c.customer_id相同。引擎的行为与前面的示例相同;检查=上是否至少有1行与orders中的customer_id相匹配。

因此,customers=的工作方式相同。