SQL Server 2012(性能调优查询)

SQL Server 2012 (performance tuning queries)

我有一个快速的性能问题。我有一个 select 语句如下。 如果所有表都被索引并且非常庞大(每个表超过百万条记录),哪个会更快。

SELECT A.col1, B.col2, C.col3, D.col4
FROM tableA A WITH (NOLOCK) 
INNER JOIN tableB B WITH (NOLOCK) ON A.col1 = B.col1
INNER JOIN tableC WITH (NOLOCK) ON B.col2 = C.col2
INNER JOIN tableD WITH (NOLOCK) ON C.col3 = D.col3
INNER JOIN tableE WITH (NOLOCK) ON D.col4 = E.col4
INNER JOIN tableF WITH (NOLOCK) ON E.col5 = F.col5
INNER JOIN tableG WITH (NOLOCK) ON F.col6 = G.col6
WHERE A.col1 = 95
AND B.col2 = 96
AND C.col3 = 97
AND G.col4 = 98 

SELECT A.col1, B.col2, C.col3, D.col4
FROM tableA A WITH (NOLOCK) 
INNER JOIN tableB B WITH (NOLOCK) ON A.col1 = B.col1 AND A.col1 = 95 AND B.col2 = 96
INNER JOIN tableC WITH (NOLOCK) ON B.col2 = C.col2  AND C.col3 = 97
INNER JOIN tableD WITH (NOLOCK) ON C.col3 = D.col3
INNER JOIN tableE WITH (NOLOCK) ON D.col4 = E.col4
INNER JOIN tableF WITH (NOLOCK) ON E.col5 = F.col5
INNER JOIN tableG WITH (NOLOCK) ON F.col6 = G.col6 AND G.col4 = 98

您编写的查询与 sql 服务器中实际执行的查询非常不同,sql 服务器优化器会互操作它认为性能最佳的查询。

在给定的场景中 sql 服务器优化器足够智能,可以看到两个查询本质上是相同的,并且会提出相同的执行计划。

因此我认为这两个查询的查询性能是一样的。

附带说明,因为您对查询中的每个 table 使用了 table 提示 WITH (NOLOCK),这相当于将事务隔离级别设置为读取未提交,您可以清理通过删除所有这些 table 提示并在执行查询之前将事务隔离级别更改为未提交读取来稍微改进您的查询......

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
GO

<Your query here>
GO

测试

我在 AdventureWorks2012 中写了两个不同的查询,一个在 WHERE 子句中使用过滤条件,一个在 ON 子句中使用过滤条件。

SELECT
    s.SalesOrderID,
    s.CustomerID,
    p.FirstName
FROM Sales.SalesOrderHeader AS s
 INNER JOIN    Sales.Customer AS c    ON s.CustomerID = c.CustomerID
 INNER JOIN    Person.Person    AS p  ON c.PersonID = p.BusinessEntityID  
WHERE C.CustomerID = 29825
 AND  p.FirstName = 'James'
GO

SELECT
    s.SalesOrderID,
    s.CustomerID,
    p.FirstName
FROM Sales.SalesOrderHeader AS s
 INNER JOIN    Sales.Customer AS c    ON s.CustomerID = c.CustomerID
                                     AND C.CustomerID = 29825
 INNER JOIN    Person.Person    AS p  ON c.PersonID = p.BusinessEntityID  
                                     AND p.FirstName = 'James'
GO

现在,如果您查看这两个查询的执行计划,它们是相同的。