表扫描和索引

时间:2011-05-02 00:36:25

标签: sql indexing

我已经检查了我经常运行的执行缓慢的查询的执行情况。它显示了一个大表的表扫描。

以下是查询:

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)OR [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

最后,问题是:

我应该添加哪些索引来摆脱表扫描并加快速度?

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

这里有几个可能性......

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


否则,它似乎是由于子查询的连接。如果是这样,SQL Server确定(fldPlayerDateAdded >= DATEADD(dd, - 4, @DateAdded))是最重要的谓词。所以它首先生成子查询结果,然后加入tblHero表。这至少提供了两个选项......

编辑 - 部分原因可能是ORDER BY子句全部来自子查询。可能在没有ORDER BY的情况下尝试,看看是否有任何影响。

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

或者,要保持相同的基本执行计划,但加快速度,请在tblHero的索引中包含字段fldHeroOwner。


注意:提供完整的实际执行计划以更好地确定正在发生的事情以及如何减轻其影响可能对您有用。

答案 2 :(得分:0)

你可以在Sql stament的末尾使用OPTION(RECOMPILE)提示,这个提示强制重新编译查询计划,这个选项在使用sql语句时使用的是带有传递给de sp的不同参数,只是做一个测试。