我已经在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
我的问题是如何更好地索引表以加快数据检索速度?还是我需要以其他方式处理数据提取?
答案 0 :(得分:4)
我认为您在这里不能做很多事情。
查询必须从索引中读取所有25M行以对其进行计数。但是,2500万行不是很多,我希望在现代硬件上花费不到4分钟。 只需读取100MB的数据(好的,实际上是200MB,但从磁盘读取200MB的时间应该不需要4分钟)。
服务器负载沉重吗?该表中有很多插入内容吗?
您可以通过在表中将WhoWon
列定义为NOT NULL
来进行一些小的改进。您真的有NULL值吗?
然后在查询中使用COUNT(*)
代替count(WhoWon)
。
如果该查询经常运行,但是表中的数据变化不是很频繁,则可以创建一个索引视图,该视图实质上会实现/缓存/预先计算这些计数,因此可以从该视图运行查询会更快。
答案 1 :(得分:2)
您也许可以通过使用窗口功能来加快速度:
SELECT WhoWon, count(*) AS Total,
count(*) * 100.0 / sum(count(*)) over () as PercentWinner
FROM [test].[dbo].[7And11SidedDiceGame]
GROUP BY WhoWon;
这不提供单独的print
语句。
为提高性能,请尝试在(WhoWon)
上建立索引。