2011-05-10 46 views
3

版:SQL Server 2008 R2的获取SQL Server使用索引查找+键查找,而不是聚集索引扫描,而不(FORCESEEK)

数据库:AdventureWorks的2008R2从http://msftdbprodsamples.codeplex.com/releases/view/55926

查询:

SELECT TOP 10 
    * 
FROM 
    Person.Person --WITH (FORCESEEK) 
WHERE 
    LastName like 'Max%' 
    OR EXISTS (
     SELECT 
      1 
     FROM 
      Person.PersonPhone 
     WHERE 
      Person.PersonPhone.BusinessEntityID = Person.Person.BusinessEntityID 
      AND Person.PersonPhone.PhoneNumber LIKE '122%' 
    ) 
ORDER BY Person.Person.BusinessEntityID DESC 


没有任何的查询提示,SQL Server将使用聚集索引扫描,这是IO密集型:

Table 'PersonPhone'. Scan count 14170, logical reads 28446, physical reads 15, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'Person'. Scan count 1, logical reads 2844, physical reads 3, read-ahead reads 3215, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 


随着WITH (FORCESEEK)查询提示,SQL Server将选择索引查找+键查找,完成速度更快,是500X亲切的IO:

Table 'Person'. Scan count 1, logical reads 59, physical reads 22, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'PersonPhone'. Scan count 1, logical reads 2, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 


我的问题是,是否有任何如何让SQL Server在没有任何查询提示的情况下使用更好的计划?可能添加索引?或者更改配置参数?还是SQL Server的查询优化器无能为力?

下面是从http://msdn.microsoft.com/en-us/library/bb510478.aspx宝石:

查询优化规则和基数的不良估计也会导致优化器执行表或索引扫描操作,而不是一个索引时查询使用IN或LIKE作为搜索寻求谓词。

+1

SQL Server将自动参数化一些查询 - 我不知道具体情况,但是,它可能是它试图优化上面的任何LIKE ...值,并且因此正在为此做出糟糕的计划选择特定的搜索。 – 2011-05-10 06:36:59

+0

@marc_s,如果您阅读了这个问题,您可以看到没有任何查询提示,查询优化器将选择需要500倍以上IO的计划。也许它发现我的磁盘闲置并渴望工作?这可能是一个很好的理由。无论如何,假设你再次读过这个问题,你可以看到我正在寻求一种方法来帮助查询优化器在没有FORCESEEK的情况下选择更好的计划。 – sayap 2011-05-10 06:38:43

+0

我不认为SQL Server会查找硬件,并决定特定的计划是好的,因为硬件目前闲置 - 计划创建是昂贵的。资源 - 并且计划通常是在考虑到重用的情况下创建的。 – 2011-05-10 06:57:32

回答

3

这是一个版本,展示'体面'的IO数字,而不诉诸FORCESEEK。 有趣的是,这个可怕的查询执行“更好”。

免责声明:本可以执行的“马克斯%”和“122%”更好,但如果该计划被重用为“M%”和“%”是另一回事,它会表现如何?

SELECT TOP 10 * 
FROM Person.Person P 
INNER JOIN (
SELECT BusinessEntityID 
FROM Person.Person --WITH (FORCESEEK) 
WHERE LastName like 'Max%'  

UNION 

SELECT BusinessEntityID 
FROM Person.Person --WITH (FORCESEEK) 
WHERE EXISTS (  SELECT   *  FROM   
    Person.PersonPhone  WHERE   Person.PersonPhone.BusinessEntityID = Person.Person.BusinessEntityID   AND Person.PersonPhone.PhoneNumber LIKE '122%' ) 
) NOTNICE 
ON NOTNICE.BusinessEntityID = P.BusinessEntityID 
ORDER BY P.BusinessEntityID DESC 
+0

谢谢,这个工程。不幸的是,它不是很“友好”。 – sayap 2011-05-10 07:32:03

+1

那么,在SQLAlchemy中,没有“不ORM友好”之类的东西。我已经成功实现了这一点。再次感谢您的答复。 – sayap 2011-05-10 08:56:10

相关问题