如何使用 2500 万行正确索引 SQL 服务器 table

How to properly index SQL Server table with 25 million rows

我在 SQL Server 2008 R2 中创建了一个 table 如下:

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

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

我不认为你能在这里做很多事情。

查询必须从索引中读取所有 2500 万行才能对其进行计数。不过,2500 万行并不算多,我希望在现代硬件上花费不到 4 分钟。 它只有 100MB 的数据要读取(好吧,实际上它更多,比如说 200MB,但从磁盘读取 200MB 应该不需要 4 分钟)。

服务器负荷大吗?这个 table 有很多插入吗?

您可以通过将 WhoWon 列定义为 table 中的 NOT NULL 来稍作改进。你真的有 NULL 值吗?

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

如果此查询经常 运行,但 table 中的数据不会经常更改,您可以创建一个索引视图,该视图基本上 materialise/cache/pre-calculate 这些计数,因此 运行 关闭此类视图的查询会快得多。

您可以使用 window 函数来加快速度:

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

这不提供单独的 print 声明。

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