如何使用 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)
上尝试索引。
我在 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)
上尝试索引。