它执行第一个WHERE子句或JOIN子句

问题描述 投票:12回答:5

哪个子句在SELECT语句中首先执行?

我在此基础上对select查询有疑问。

考虑下面的例子

SELECT * 
FROM #temp A 
INNER JOIN #temp B ON A.id = B.id 
INNER JOIN #temp C ON B.id = C.id 
WHERE A.Name = 'Acb' AND B.Name = C.Name
  1. 是否,首先它检查WHERE条款,然后执行INNER JOIN
  2. 首先JOIN然后检查条件?

如果它首先执行JOIN然后WHERE条件;如何在不同JOINs的条件下表现更好?

sql sql-server select join where
5个回答
16
投票

查询处理的概念顺序是:

1. FROM
2. WHERE
3. GROUP BY
4. HAVING
5. SELECT
6. ORDER BY

但这只是一个概念性的顺序。事实上,引擎可能会决定重新安排条款。这是证据。让我们制作2个表,每个表1000000行:

CREATE TABLE test1 (id INT IDENTITY(1, 1), name VARCHAR(10))
CREATE TABLE test2 (id INT IDENTITY(1, 1), name VARCHAR(10))


;WITH cte AS(SELECT -1 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) d FROM
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t1(n) CROSS JOIN
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t2(n) CROSS JOIN
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t3(n) CROSS JOIN
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t4(n) CROSS JOIN
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t5(n) CROSS JOIN
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t6(n))

INSERT INTO test1(name) SELECT 'a' FROM cte

现在运行2个查询:

SELECT * FROM dbo.test1 t1
JOIN dbo.test2 t2 ON t2.id = t1.id AND t2.id = 100
WHERE t1.id > 1


SELECT * FROM dbo.test1 t1
JOIN dbo.test2 t2 ON t2.id = t1.id
WHERE t1.id = 1

注意首先将在join条件下过滤掉大多数行,在where条件下过滤第二行。看看生产计划:

1 TableScan - 谓词:[测试]。[dbo]。[test2]。[id]为[t2]。[id] =(100)

2 TableScan - 谓词:[测试]。[dbo]。[test2]。[id] as [t2]。[id] =(1)

这意味着在第一个查询优化时首先决定评估join条件以过滤掉行,然后在第二个中首先评估where子句。


8
投票

查询处理阶段的逻辑顺序是:

  1. FROM - 包括JOINs
  2. WHERE
  3. GROUP BY
  4. HAVING
  5. SELECT
  6. ORDER BY

你甚至可以在你的JOINs或WHERE条款中拥有尽可能多的条件。喜欢:

Select * from #temp A 
INNER JOIN #temp B ON A.id = B.id AND .... AND ... 
INNER JOIN #temp C ON B.id = C.id AND .... AND ...
Where A.Name = 'Acb'
AND B.Name = C.Name
AND ....

3
投票

你可以参考MSDN

查询选择的行首先由FROM子句连接条件过滤,然后是WHERE子句搜索条件,然后是HAVING子句搜索条件。可以在FROM或WHERE子句中指定内部联接,而不会影响最终结果。

您还可以在执行查询之前使用SET SHOWPLAN_ALL ON来显示查询的执行计划,以便您可以测量两者中的性能差异。


1
投票

你可以参考这个join optimization

SELECT * FROM T1 INNER JOIN T2 ON P1(T1,T2)
                 INNER JOIN T3 ON P2(T2,T3)
  WHERE P(T1,T2,T3)

嵌套循环连接算法将以下列方式执行此查询:

FOR each row t1 in T1 {
  FOR each row t2 in T2 such that P1(t1,t2) {
    FOR each row t3 in T3 such that P2(t2,t3) {
      IF P(t1,t2,t3) {
         t:=t1||t2||t3; OUTPUT t;
      }
    }
  }
}

0
投票

如果你来到这个网站关于logical query processing的问题,你真的需要阅读this article on ITProToday by Itzik Ben-Gan

Figure 3: Logical query processing order of query clauses

1 FROM 
2 WHERE 
3 GROUP BY 
4 HAVING 
5 SELECT
    5.1 SELECT list
    5.2 DISTINCT
6 ORDER BY 
7 TOP / OFFSET-FETCH
© www.soinside.com 2019 - 2024. All rights reserved.