2011-05-02 99 views
2

我检查,我经常遇到一个缓慢的执行查询的执行。它显示了一张大桌子的表扫描。表扫描和索引

下面是查询:

declare @DateAdded datetime 

set @DateAdded = '5/1/2011' 

SELECT  tblHero.fldHeroName,players.Alliance, 
    tblHero.fldHeroOwner, players.ActIndex, players.fldPlayerCities, 
    tblHero.fldHeroLevel, tblHero.fldHeroPower, 
    players.fldPlayerPrestige, players.fldPlayerName 
FROM   tblHero INNER JOIN 
(
    SELECT  MAX(fldPlayerCities) AS fldPlayerCities, MAX(fldPlayerAlliance) AS  Alliance, 
      MAX(fldPlayerPrestige) AS fldPlayerPrestige, fldPlayerName, 
      MAX(fldPlayerPrestige) - AVG(fldPlayerPrestige) AS ActIndex 
    FROM tblPlayer WHERE (fldPlayerDateAdded >= DATEADD(dd, - 4, @DateAdded)) GROUP BY  fldPlayerName 
) players 
ON tblHero.fldHeroOwner = players.fldPlayerName 
WHERE  (tblHero.fldHeroIsHistoric = 1 or fldHeroLevel = 100) and 
    fldHeroDateAdded = @DateAdded 
ORDER BY players.ActIndex, players.fldPlayerCities, players.fldPlayerPrestige 

从表扫描的谓词是:

[DBO] [tblHero] [fldHeroDateAdded] = [@ DateAdded] AND([DBO]。 [tblHero] [fldHeroIsHistoric] =(1)或[DBO] [tblHero] [fldHeroLevel] =(100))

以下指数在桌子上:。

CREATE NONCLUSTERED INDEX IX_tblHero_2 ON dbo.tblHero 
    (
    fldHeroDateAdded DESC, 
    fldHeroIsHistoric DESC 
    ) WITH(STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,  ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 
CREATE NONCLUSTERED INDEX IX_tblHero_3 ON dbo.tblHero 
    (
    fldHeroDateAdded DESC, 
    fldHeroLevel DESC 
    ) WITH(STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,  ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 

最后,问题:

我要补充哪些索引摆脱表扫描和速度这件事的?

回答

0

有一对夫妇在这里posibilities的...

存储在一个存储过程的查询,并索引存储过程后创建的?如果是这样,请重新编译为存储过程以强制SQL Server生成新的执行计划。


否则,它会出现,这是由于在子查询的连接。如果是这样,SQL Server在确定(fldPlayerDateAdded >= DATEADD(dd, - 4, @DateAdded))是最重要的谓语。所以它首先生成子查询结果,然后加入到tblHero表中。这使得至少有两个选项...

编辑 - 这可能是部分原因是由于ORDER BY子句从子查询的所有之中。可能尝试没有ORDER BY,看看这是否有任何影响。

首先,如果不存在,您可以将(fldPlayerDateAdded,fldPlayerName)上的索引添加到tblPlayer。这可能会允许优化器先过滤tblHero表,然后加入到子查询中。

此外,要保持基本的执行计划,但加快步伐,包括在tblHero你的索引字段fldHeroOwner。


注:这可能是有用的,为您提供完整的实际执行计划,以更好地确定发生了什么,以及如何减轻反对。

2

你需要tblPlayer上fldPlayerDateAdded指数是肯定的,因为它是做一个日期范围搜索。您也可以尝试在fldPlayerName上添加单独的索引。复合索引将执行相同的功能,但会将它们排列在一起,这对于这种情况可能没有问题,但对于您可能或不可能拥有的所有不同情况而言,并不适合。日期范围查询也适用于聚簇索引(一般范围),但您可能已经在PK上有聚簇索引。

+0

与OP的问题无关,你能否详细说明'日期范围查询也适用于聚簇索引,(一般范围)''?也就是说,除了一个简单的事实,即所有索引在聚集时都会获得更高的性能增益? – MatBailie 2011-05-02 01:11:20

+1

任何范围查询更适合聚簇,因为聚簇索引是有序的。因此,当您在[日期]和[日期2]之间查找10到200之间的日期或日期之前的日期时,由于它们是有序的(索引数据是连续的) ,因此执行速度更快。 – 2011-05-02 02:59:37

+0

问题是肯定的位字段,IsHistoric。如果我从查询中删除它,表扫描就会消失。即使单个索引每个字段似乎也没有什么区别。 – Darthg8r 2011-05-02 22:17:49

0

您可以在Sql stament的末尾使用OPTION(RECOMPILE)提示,this提示力重新编译查询计划,当SQL语句使用通过脱SP型动物的参数,只是做一个测试这个选项是有用的。