如何正确索引具有2500万行的SQL Server表

问题描述 投票:1回答:2

我在SQL Server 2008 R2中创建了一个表,如下所示:

CREATE TABLE [dbo].[7And11SidedDiceGame]
(
    [Dice11Sides] [INT] NULL,
    [Dice7Sides] [INT] NULL,
    [WhoWon] [INT] NULL
)

我添加了以下索引:

CREATE NONCLUSTERED INDEX [idxWhoWon] 
ON [dbo].[7And11SidedDiceGame] ([WhoWon] ASC)

然后我创建了一个WHILE循环来插入2500万个随机生成的行来统计结果以进行统计分析。

一旦我优化了Insert函数(在循环之前和之后使用BEGIN TRAN和COMMIT TRAN),While循环运行得体。但是,分析数据需要很长时间。例如:使用以下语句需要大约4分钟才能执行:

DECLARE @TotalRows real

SELECT @TotalRows = COUNT(*) 
FROM [test].[dbo].[7And11SidedDiceGame]

PRINT REPLACE(CONVERT(VARCHAR, CAST(@TotalRows AS money), 1),'.00','') 

SELECT 
    WhoWon, COUNT(WhoWon) AS Total,  
    ((COUNT(WhoWon) * 100) / @TotalRows) AS PercentWinner
FROM 
    [test].[dbo].[7And11SidedDiceGame]
GROUP BY 
    WhoWon

我的问题是如何更好地索引表格以加快数据检索?或者我是否需要以不同的方式处理数据?

sql sql-server sql-server-2008-r2
2个回答
4
投票

我认为你在这里做不了什么。

查询必须从索引中读取所有25M行以对其进行计数。虽然,25M行并不是那么多,我希望在现代硬件上花费不到4分钟。它只能读取100MB的数据(好吧,实际上它更多,比方说,200MB,仍然不需要花4分钟读取磁盘上的200MB)。

服务器是否负载很重?这张表中有很多插页吗?

您可以通过在表格中将WhoWon列定义为NOT NULL来进行小改进。你真的有NULL值吗?

然后在查询中使用COUNT(*)而不是count(WhoWon)

如果此查询经常运行,但表中的数据不会经常更改,则可以创建一个基本上实现/缓存/预先计算这些计数的索引视图,因此将运行此类视图的查询将会很多快点。


2
投票

您可以通过使用窗口函数来加快速度:

SELECT WhoWon, count(*) AS Total,   
       count(*) * 100.0 / sum(count(*)) over ()  as PercentWinner
FROM [test].[dbo].[7And11SidedDiceGame]
GROUP BY WhoWon;

这不提供单独的print声明。

为了提高性能,请尝试使用(WhoWon)上的索引。

© www.soinside.com 2019 - 2024. All rights reserved.