使用count时如何提高性能

时间:2011-07-13 13:23:44

标签: sql performance sql-server-2008

我的数据库是SQL SERVER 2008

我有一个包含1亿行和50列的大表。

所有数据类型都是int。

然后,我的查询就像....

Select Count(distinct col5) , Count(distinct col8) , Sum(Col 30) , Sum(Col 49) 
Group by Col1 

Select Count(distinct col5) , Count(distinct col8) , Sum(Col 30) , Sum(Col 49) 
Group by Col1,col2

.....


Select Count(distinct col5) , Count(distinct col8) , Sum(Col 30) , Sum(Col 49) 
Group by Col1 ,Col2,Col3,Col4,Col6,Col7

(about 180 queries ...like above)

但是当我使用count distinct时,性能非常差。

那么,谁可以教我如何改进呢?

在我的情况下,使用最佳解决方案需要多长时间?

非常感谢你的建议......

3 个答案:

答案 0 :(得分:3)

这些查询(没有WHERE子句)很难被优化,因为他们需要访问每条记录来计算总和,无论如何。

全表扫描和保存结果的临时表是最佳解决方案,而这正是您计划中最可能拥有的。

答案 1 :(得分:2)

Indexing列会提高性能,但插入/更新可能会变慢。

修改
在评论中建议对索引进行更多测试。我得到了这些结果:(有和没有索引) enter image description here

使用此查询:( MAXDOP将查询限制为使用一个处理器以获得更具可比性的计划,而没有MAXDOP暗示成本为36%对64%)

SELECT COUNT(DISTINCT fkCustomCultureID), SUM(fkCustomCultureTypeID)
FROM tblTest
GROUP BY fkCategoryTypeID
OPTION (MAXDOP 1)

在这张桌子上:

CREATE TABLE [dbo].[TblTest](
    [fkID] [sql_variant] NOT NULL,
    [fkCustomCultureID] [bigint] NOT NULL,
    [fkCategoryTypeID] [int] NOT NULL,
    [fkCustomCultureTypeID] [int] NOT NULL
) ON [PRIMARY]

GO

CREATE NONCLUSTERED INDEX [IX_Test1] ON [dbo].[TblTest] 
(
    [fkCustomCultureID] ASC,
    [fkCategoryTypeID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

答案 2 :(得分:0)

如果你并不总是需要所有列,只是想把它扔出去,你是否考虑过拆分表?它应该没问题,只要你能以这种方式改变表格(通常情况就是如此)

如果将表拆分为5个(大约)10列的表并为每个当前存在的行分配ID(聚集索引),则最终必须扫描最多5倍的磁盘(提供所有列是相同的,记住,如果你没有索引,那么它将始终检索所有列的所有列。

除了在每一列上抛出一个索引之外,我建议你查看你的查询并尝试确定是否有一些被称为很少的列和其他一直被调用的列(特别是一起)。当我在过去这样做时,我看到了相当大的改进,直接将表分成“总是”,“经常”,“很少”和“几乎从不”表以及“通常在一起”表或两个表

同样可能有助于在共同的group by子句中执行此操作,因为至少有几列可能比其他列更常见。

如果你真的想要更好的性能,我也建议你可以考虑更改磁盘驱动器并升级SQL Server上的ram,你的表应该使用大约20GB的空间,当前的磁盘驱动器需要多长时间才能读取将20GB的数据从磁盘变成ram?这将是你的查询执行时间的下限(除非它总是在ram中,在这种情况下,即使有这么多的数据查询也不应该花太长时间)