SQL优化查询

时间:2009-05-26 14:57:36

标签: sql sql-server performance

以下MSSQL2005查询非常慢。我觉得他们应该成为加快速度的方法,但我不确定如何。请注意,我编辑了内部联接以使用select语句使(对于阅读此问题的人)更明显的是发生了什么,尽管这对速度没有影响(执行计划可能是相同的两种方式)。有趣的是,我从来没有实际使用关键字值组来计算任何数量,但我不确定是否有办法利用它。

select top 1 cde.processPath as 'keywordValue', count(*) as 'total'
from dbo.ClientDefinitionEntry AS cde INNER JOIN dbo.KeywordValueGroups  AS kvg
ON cde.keywordGroupId = kvg.keywordValueGrpId
where kvg.[name] = @definitionName
group by cde.processPath
order by total desc      

编辑:显然,人们一直抱怨我使用子查询。事实上,它没有任何区别。我在发布此问题之前添加了它们,以便更容易看到发生了什么。但是他们只是让事情变得更加混乱,所以我改变它不使用它们。

编辑:正在使用的索引:

ClientDefinitionEntry:
IX_ClientDefinitionEntry   |nonclustered located on PRIMARY|clientId, keywordGroupId

KeyWordValueGroups
IX_KeywordValueGroups      |nonclustered located on PRIMARY|keywordValueGrpId
IX_KeywordValueGroups_2    |nonclustered located on PRIMARY|version
IX_KeywordValueGroups_Name |nonclustered located on PRIMARY|name

5 个答案:

答案 0 :(得分:3)

执行计划如何? 通过查看它,您将了解查询的哪一部分占用最多的时间/资源。

您是否对要过滤的列进行了索引?您是否对用于加入的列编制索引?您是否对用于排序的列进行了索引?

一旦你看了这个,并且查询仍然很慢,你可以看一下你的数据库/表是如何分段的(dbcc showcontig),看看是否有必要重建索引。登记/> 制定维护计划可能会有所帮助,该计划会定期重建索引。

答案 1 :(得分:3)

使用此选项运行查询:

设置SHOWPLAN_TEXT

并将结果添加到问题中。

另请检查您的统计信息是否是最新的:

SELECT 
    object_name = Object_Name(ind.object_id),
    IndexName = ind.name,
    StatisticsDate = STATS_DATE(ind.object_id, ind.index_id)
FROM SYS.INDEXES ind
order by STATS_DATE(ind.object_id, ind.index_id) desc

有关索引,表定义和外键的信息会很有帮助。

答案 2 :(得分:2)

确实没有足够的信息可以知道。如果您在该查询中遇到性能问题,那么表必须具有非常重要的数据量,并且您必须缺少重要的索引。

哪些索引肯定会有所帮助,这在很大程度上取决于表的大小,以及在较小程度上取决于KeywordGroupId和KeywordValueGrpId字段中值的分布。

缺少任何其他信息,我想说您要确保dbo.KeywordValueGroups.[name]被编入索引,以及dbo.ClientDefinitionEntry.[keywordGroupId]

由于编写查询的方式,仅dbo.KeywordValueGroups.[keywordValueGrpId]上的索引无法帮助,但[name], [keywordValueGrpId]上的复合索引可能会有所帮助。如果您有该索引,则不需要[name]上的专用索引。

仅基于直觉,我可能会担心[name]上的索引是必须,而cde.keywordGroupId可能很重要。 [name], [keywordValueGrpId]上的复合索引是否有帮助,取决于具有相同[名称]的记录数。

唯一可以确定的方法是添加索引,看看会发生什么。

您还需要考虑此查询运行的频率(因此,使其快速运行的重要性)以及基础数据更改的频率。根据您的具体情况,速度的提高可能无法证明维护索引的额外成本。

答案 3 :(得分:2)

我确保你有以下索引。

KeywordValueGroups上的ID。

KeywordValueGroups上的名称。

ClientDefinitionEntry上的ID,其中包含processPath的INCLUDE。

CREATE INDEX [IX_ClientDefinitionEntry_Id_ProcessPath] ON [dbo].[ClientDefinitionEntry] ( [keywordGroupId] ASC ) INCLUDE ( [processPath]) ON [PRIMARY]
CREATE INDEX [IX_KeywordValueGroups_Id] ON [dbo].[KeywordValueGroups] ( [keywordValueGrpId] ASC )
CREATE INDEX [IX_KeywordValueGroups_Name] ON [dbo].[KeywordValueGroups] ( [name] ASC )

我还将查询更改为以下内容。

select top 1
    cde.processPath as 'keywordValue',
    count(*) as 'total'
from
    dbo.ClientDefinitionEntry AS cde
INNER JOIN
    dbo.KeywordValueGroups  AS kvg
ON
    cde.keywordGroupId = kvg.keywordValueGrpId
where
    kvg.[name] = @definitionName
group by
    processPath
order by
    total desc

答案 4 :(得分:0)

不确定我们谈论的记录有多少但是这个:   按总额排序 在计算列上,意味着每行上的每个计算都必须在排序完成之前完成。可能这是减缓它的事情之一,但我认为没有办法摆脱那个特定的问题。如果您在加入后只有一些记录,则不会有问题,但如果有很多记录可能会出现问题。

我首先专注于索引。我们经常忘记,当我们创建foriegn键时,它们不会自动编入索引。检查连接的两个部分是否都已编入索引。

由于您在参数中传递值,因此您可能还有参数嗅探问题。谷歌这是解决这个问题的技巧。