堆上非聚集索引与聚集索引的性能

发布于 2024-10-19 06:23:54 字数 1459 浏览 5 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小霸王臭丫头 2024-10-26 06:23:54

为了检查您的请求,我按照此方案创建了 2 个表:

  • 代表余额信息的 790 万条记录。
  • 身份字段从 1 计数到 790 万
  • 数字字段将记录分为大约 50 万组。

第一个名为heap 的表在字段group 上获得了非聚集索引。第二个表名为 clust,在名为 key 的顺序字段上有一个聚集索引,在字段 group 上有一个非聚集索引。

测试在I5 M540 处理器,具有 2 个超线程核心、4Gb 内存和 64 位 Windows 7。

Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (X64) 
Apr  2 2010 15:48:46 
Developer Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)  

2011 年 3 月 9 日更新:我通过运行以下 .net 代码并在 Sql Server Profiler 中记录持续时间、CPU、读取、写入和行计数,进行了第二次更广泛的基准测试。 (所使用的 CommandText 将在结果中提及。)

注意:CPU 和持续时间以毫秒表示

  • 1000 次查询
  • 结果中消除了零 CPU 查询
  • 从结果中删除 0 行受影响的行
int[] idList = new int[] { 6816588, 7086702, 6498815 ... }; // 1000 values here.
using (var conn = new SqlConnection(@"Data Source=myserver;Initial Catalog=mydb;Integrated Security=SSPI;"))
            {
                conn.Open();
                using (var cmd = new SqlCommand())
                {
                    cmd.Connection = conn;
                    cmd.CommandType = CommandType.Text;
                    cmd.CommandText = "select * from heap where common_key between @id and @id+1000"; 
                    cmd.Parameters.Add("@id", SqlDbType.Int);
                    cmd.Prepare();
                    foreach (int id in idList)
                    {
                        cmd.Parameters[0].Value = id;

                        using (var reader = cmd.ExecuteReader())
                        {
                            int count = 0;
                            while (reader.Read())
                            {
                                count++;
                            }
                            Console.WriteLine(String.Format("key: {0} => {1} rows", id, count));
                        }
                    }
                }
            }

更新于 2011 年 3 月 9 日结束

SELECT 性能

为了检查性能数字,我对堆表和簇表执行了一次以下查询:

select * from heap/clust where group between 5678910 and 5679410
select * from heap/clust where group between 6234567 and 6234967
select * from heap/clust where group between 6455429 and 6455729
select * from heap/clust where group between 6655429 and 6655729
select * from heap/clust where group between 6955429 and 6955729
select * from heap/clust where group between 7195542 and 7155729

此基准测试的结果针对

rows  reads CPU   Elapsed 
----- ----- ----- --------
1503  1510  31ms  309ms
401   405   15ms  283ms
2700  2709  0ms   472ms
0     3     0ms   30ms
2953  2962  32ms  257ms
0     0     0ms   0ms

2011 年 3 月 9 日更新
cmd.CommandText =“从堆中选择*,其中@id和@id+1000之间的组”;

  • 721 行有 > 0 CPU 并影响超过 0 行
Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts    1001      69788    6368         -         
Cpu            15        374      37   0.00754
Reads        1069      91459    7682   1.20155
Writes          0          0       0   0.00000
Duration   0.3716   282.4850 10.3672   0.00180

更新于 2011 年 3 月 9 日结束


对于表clust,结果是:

rows  reads CPU   Elapsed 
----- ----- ----- --------
1503  4827  31ms  327ms
401   1241  0ms   242ms
2700  8372  0ms   410ms
0     3     0ms   0ms
2953  9060  47ms  213ms
0     0     0ms   0ms

2011 年 3 月 9 日更新
cmd.CommandText =“从@id和@id+1000之间的组中选择*”;

  • 721 行有 > 0 CPU 并影响超过 0 行
Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts    1001      69788    6056         -
Cpu            15        468      38   0.00782
Reads        3194     227018   20457   3.37618
Writes          0          0       0       0.0
Duration   0.3949   159.6223 11.5699   0.00214

更新于 2011 年 3 月 9 日结束


SELECT WITH JOIN 性能

cmd.CommandText = "select * from heap/clust h join keys k on h.group = k.group where h.group between @id and @id+1000";


结果该基准测试的

873行有> 0 个 CPU 并影响超过 0 行

Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts    1009       4170    1683         -
Cpu            15         47      18   0.01175
Reads        2145       5518    2867   1.79246
Writes          0          0       0   0.00000
Duration   0.8215   131.9583  1.9095   0.00123

此基准测试的结果针对 clust

865 行有 > 0 CPU 并影响超过 0 行的

Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts    1000       4143    1685         -
Cpu            15         47      18   0.01193
Reads        5320      18690    8237   4.97813
Writes          0          0       0   0.00000
Duration   0.9699    20.3217  1.7934   0.00109

UPDATE 性能

第二批查询是更新语句:

update heap/clust set amount = amount + 0 where group between 5678910 and 5679410
update heap/clust set amount = amount + 0 where group between 6234567 and 6234967
update heap/clust set amount = amount + 0 where group between 6455429 and 6455729
update heap/clust set amount = amount + 0 where group between 6655429 and 6655729
update heap/clust set amount = amount + 0 where group between 6955429 and 6955729
update heap/clust set amount = amount + 0 where group between 7195542 and 7155729

此基准测试的结果为 heap

rows  reads CPU   Elapsed 
----- ----- ----- -------- 
1503  3013  31ms  175ms
401   806   0ms   22ms
2700  5409  47ms  100ms
0     3     0ms   0ms
2953  5915  31ms  88ms
0     0     0ms   0ms

2011 年 3 月 9 日更新
cmd.CommandText =“更新堆集数量=数量+@id,其中@id和@id+1000之间的组”;

  • 811 行有 > 0 CPU 并影响超过 0 行
Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts    1001      69788    5598       811         
Cpu            15        873      56   0.01199
Reads        2080     167593   11809   2.11217
Writes          0       1687     121   0.02170
Duration   0.6705   514.5347 17.2041   0.00344

更新于 2011 年 3 月 9 日结束


clust 的基准测试结果:

rows  reads CPU   Elapsed 
----- ----- ----- -------- 
1503  9126  16ms  35ms
401   2444  0ms   4ms
2700  16385 31ms  54ms
0     3     0ms   0ms 
2953  17919 31ms  35ms
0     0     0ms   0ms

2011 年 3 月 9 日更新
cmd.CommandText =“更新集群集数量=数量+@id,其中@id和@id+1000之间的组”;

  • 853 行有 > 0 CPU 并影响超过 0 行
Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts    1001      69788    5420         -
Cpu            15        594      50   0.01073
Reads        6226     432237   33597   6.20450
Writes          0       1730     110   0.01971
Duration   0.9134   193.7685  8.2919   0.00155

更新于 2011 年 3 月 9 日结束


DELETE 基准测试

我运行的第三批查询是删除语句

delete heap/clust where group between 5678910 and 5679410
delete heap/clust where group between 6234567 and 6234967
delete heap/clust where group between 6455429 and 6455729
delete heap/clust where group between 6655429 and 6655729
delete heap/clust where group between 6955429 and 6955729
delete heap/clust where group between 7195542 and 7155729

此基准测试的结果:

rows  reads CPU   Elapsed 
----- ----- ----- -------- 
1503  10630 62ms  179ms
401   2838  0ms   26ms
2700  19077 47ms  87ms
0     4     0ms   0ms
2953  20865 62ms  196ms
0     4     0ms   9ms

2011 年 3 月 9 日更新
cmd.CommandText = "删除@id和@id+1000之间的组的堆";

  • 724 行有 > 0 CPU 并影响超过 0 行
Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts     192      69788    4781         -
Cpu            15        499      45   0.01247
Reads         841     307958   20987   4.37880
Writes          2       1819     127   0.02648
Duration   0.3775  1534.3383 17.2412   0.00349

更新于 2011 年 3 月 9 日结束


clust 的基准测试结果:

rows  reads CPU   Elapsed 
----- ----- ----- -------- 
1503  9228  16ms  55ms
401   3681  0ms   50ms
2700  24644 46ms  79ms
0     3     0ms   0ms
2953  26955 47ms  92ms
0     3     0ms   0ms

2011 年 3 月 9 日更新

cmd.CommandText = "删除@id和@id+1000之间的组";

  • 751 行有 > 0 CPU 并影响超过 0 行
Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts     144      69788    4648         -
Cpu            15        764      56   0.01538
Reads         989     458467   30207   6.48490
Writes          2       1830     127   0.02694
Duration   0.2938  2512.1968 24.3714   0.00555

更新于 2011 年 3 月 9 日结束


INSERT 基准测试

基准测试的最后一部分是插入语句的执行。

插入堆/簇(...)
价值观(...),
(...),
(...),
(...),
(...),
(...)


的基准测试结果:

rows  reads CPU   Elapsed 
----- ----- ----- -------- 
6     38    0ms   31ms

2011 年 3 月 9 日更新

string str = @"insert into heap (group, currency, year, period, domain_id, mtdAmount, mtdAmount, ytdAmount, amount, ytd_restated, restated, auditDate, auditUser)
                    values";

                    for (int x = 0; x < 999; x++)
                    {
                        str += string.Format(@"(@id + {0}, 'EUR', 2012, 2, 0, 100, 100, 1000 + @id,1000, 1000,1000, current_timestamp, 'test'),  ", x);
                    }
                    str += string.Format(@"(@id, 'CAD', 2012, 2, 0, 100, 100, 1000 + @id,1000, 1000,1000, current_timestamp, 'test') ", 1000);

                    cmd.CommandText = str;
  • 912 语句有 > 0 CPU
Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts    1000       1000    1000         -
Cpu            15       2138      25   0.02500
Reads        5212       7069    6328   6.32837
Writes         16         34      22   0.02222
Duration   1.6336   293.2132  4.4009   0.00440

更新于 2011 年 3 月 9 日结束


clust 的基准测试结果:

rows  reads CPU   Elapsed 
----- ----- ----- -------- 
6     50    0ms   18ms

2011 年 3 月 9 日更新

string str = @"insert into clust (group, currency, year, period, domain_id, mtdAmount, mtdAmount, ytdAmount, amount, ytd_restated, restated, auditDate, auditUser)
                    values";

                    for (int x = 0; x < 999; x++)
                    {
                        str += string.Format(@"(@id + {0}, 'EUR', 2012, 2, 0, 100, 100, 1000 + @id,1000, 1000,1000, current_timestamp, 'test'),  ", x);
                    }
                    str += string.Format(@"(@id, 'CAD', 2012, 2, 0, 100, 100, 1000 + @id,1000, 1000,1000, current_timestamp, 'test') ", 1000);

                    cmd.CommandText = str;
  • 946 条语句有 > 0 CPU
Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts    1000       1000    1000         -      
Cpu            15       2403      21   0.02157
Reads        6810       8997    8412   8.41223
Writes         16         25      19   0.01942
Duration   1.5375   268.2571  6.1463   0.00614

更新于 2011 年 3 月 9 日结束


结论

虽然使用 clustered & 访问表时会发生更多的逻辑读取,但非聚集索引(使用非聚集索引时)的性能结果是:

  • SELECT 语句相当 配备
  • 聚集索引时 UPDATE 语句更快 配备聚集索引
  • 时 DELETE 语句更快 配备聚集索引时
  • 语句更快

INSERT 当然,我的基准测试非常限于特定类型的表和非常有限的查询集,但我认为基于这些信息,我们已经可以开始说,在表上创建聚集索引实际上总是更好。

2011 年 3 月 9 日更新

从补充的结果可以看出,有限测试的结论并非在所有情况下都是正确的。

Weighted Duration

现在的结果表明,唯一受益于聚集索引的语句是更新语句。在具有聚集索引的表上,其他语句大约慢 30%。

我在一些附加图表中绘制了堆与簇的每个查询的加权持续时间。
加权持续时间堆与 Select 集群

加权持续时间堆与集群连接

加权持续时间堆与集群更新

Weighted Duration heap vs clustered for Delete

如您所见,插入语句的性能概况非常有趣。峰值是由一些数据点引起的,这些数据点需要更长的时间才能完成。
加权持续时间堆与插入集群

更新于 2011 年 3 月 9 日结束

To check your request I created 2 tables following this scheme:

  • 7.9 million records representing balance information.
  • an identity field counting from 1 to 7.9 million
  • a number field grouping the records in about 500k groups.

The first table called heap got a non clustered index on the field group. The second table called clust got a clustered index on the sequential field called key and a nonclustered index on the field group

The tests were run on an I5 M540 processor with 2 hyperthreaded cores, 4Gb memory and 64-bit windows 7.

Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (X64) 
Apr  2 2010 15:48:46 
Developer Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)  

Update on 9 Mar 2011: I did a second more extensive benchmark by running the following .net code and logging Duration, CPU, Reads, Writes and RowCounts in Sql Server Profiler. (The CommandText used will be mentioned in the results.)

NOTE: CPU and Duration are expressed in milliseconds

  • 1000 queries
  • zero CPU queries are eliminated from the results
  • 0 rows affected are eliminated from the results
int[] idList = new int[] { 6816588, 7086702, 6498815 ... }; // 1000 values here.
using (var conn = new SqlConnection(@"Data Source=myserver;Initial Catalog=mydb;Integrated Security=SSPI;"))
            {
                conn.Open();
                using (var cmd = new SqlCommand())
                {
                    cmd.Connection = conn;
                    cmd.CommandType = CommandType.Text;
                    cmd.CommandText = "select * from heap where common_key between @id and @id+1000"; 
                    cmd.Parameters.Add("@id", SqlDbType.Int);
                    cmd.Prepare();
                    foreach (int id in idList)
                    {
                        cmd.Parameters[0].Value = id;

                        using (var reader = cmd.ExecuteReader())
                        {
                            int count = 0;
                            while (reader.Read())
                            {
                                count++;
                            }
                            Console.WriteLine(String.Format("key: {0} => {1} rows", id, count));
                        }
                    }
                }
            }

End of Update on 9 Mar 2011.

SELECT performance

To check performanc numbers I performed the following queries once on the heap table and once on the clust table:

select * from heap/clust where group between 5678910 and 5679410
select * from heap/clust where group between 6234567 and 6234967
select * from heap/clust where group between 6455429 and 6455729
select * from heap/clust where group between 6655429 and 6655729
select * from heap/clust where group between 6955429 and 6955729
select * from heap/clust where group between 7195542 and 7155729

The results of this benchmark are for the heap:

rows  reads CPU   Elapsed 
----- ----- ----- --------
1503  1510  31ms  309ms
401   405   15ms  283ms
2700  2709  0ms   472ms
0     3     0ms   30ms
2953  2962  32ms  257ms
0     0     0ms   0ms

Update on 9 Mar 2011:
cmd.CommandText = "select * from heap where group between @id and @id+1000";

  • 721 Rows have > 0 CPU and affect more than 0 rows
Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts    1001      69788    6368         -         
Cpu            15        374      37   0.00754
Reads        1069      91459    7682   1.20155
Writes          0          0       0   0.00000
Duration   0.3716   282.4850 10.3672   0.00180

End of Update on 9 Mar 2011.


for the table clust the results are:

rows  reads CPU   Elapsed 
----- ----- ----- --------
1503  4827  31ms  327ms
401   1241  0ms   242ms
2700  8372  0ms   410ms
0     3     0ms   0ms
2953  9060  47ms  213ms
0     0     0ms   0ms

Update on 9 Mar 2011:
cmd.CommandText = "select * from clust where group between @id and @id+1000";

  • 721 Rows have > 0 CPU and affect more than 0 rows
Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts    1001      69788    6056         -
Cpu            15        468      38   0.00782
Reads        3194     227018   20457   3.37618
Writes          0          0       0       0.0
Duration   0.3949   159.6223 11.5699   0.00214

End of Update on 9 Mar 2011.


SELECT WITH JOIN performance

cmd.CommandText = "select * from heap/clust h join keys k on h.group = k.group where h.group between @id and @id+1000";


The results of this benchmark are for the heap:

873 Rows have > 0 CPU and affect more than 0 rows

Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts    1009       4170    1683         -
Cpu            15         47      18   0.01175
Reads        2145       5518    2867   1.79246
Writes          0          0       0   0.00000
Duration   0.8215   131.9583  1.9095   0.00123

The results of this benchmark are for the clust:

865 Rows have > 0 CPU and affect more than 0 rows

Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts    1000       4143    1685         -
Cpu            15         47      18   0.01193
Reads        5320      18690    8237   4.97813
Writes          0          0       0   0.00000
Duration   0.9699    20.3217  1.7934   0.00109

UPDATE performance

The second batch of queries are update statements:

update heap/clust set amount = amount + 0 where group between 5678910 and 5679410
update heap/clust set amount = amount + 0 where group between 6234567 and 6234967
update heap/clust set amount = amount + 0 where group between 6455429 and 6455729
update heap/clust set amount = amount + 0 where group between 6655429 and 6655729
update heap/clust set amount = amount + 0 where group between 6955429 and 6955729
update heap/clust set amount = amount + 0 where group between 7195542 and 7155729

the results of this benchmark for the heap:

rows  reads CPU   Elapsed 
----- ----- ----- -------- 
1503  3013  31ms  175ms
401   806   0ms   22ms
2700  5409  47ms  100ms
0     3     0ms   0ms
2953  5915  31ms  88ms
0     0     0ms   0ms

Update on 9 Mar 2011:
cmd.CommandText = "update heap set amount = amount + @id where group between @id and @id+1000";

  • 811 Rows have > 0 CPU and affect more than 0 rows
Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts    1001      69788    5598       811         
Cpu            15        873      56   0.01199
Reads        2080     167593   11809   2.11217
Writes          0       1687     121   0.02170
Duration   0.6705   514.5347 17.2041   0.00344

End of Update on 9 Mar 2011.


the results of this benchmark for the clust:

rows  reads CPU   Elapsed 
----- ----- ----- -------- 
1503  9126  16ms  35ms
401   2444  0ms   4ms
2700  16385 31ms  54ms
0     3     0ms   0ms 
2953  17919 31ms  35ms
0     0     0ms   0ms

Update on 9 Mar 2011:
cmd.CommandText = "update clust set amount = amount + @id where group between @id and @id+1000";

  • 853 Rows have > 0 CPU and affect more than 0 rows
Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts    1001      69788    5420         -
Cpu            15        594      50   0.01073
Reads        6226     432237   33597   6.20450
Writes          0       1730     110   0.01971
Duration   0.9134   193.7685  8.2919   0.00155

End of Update on 9 Mar 2011.


DELETE benchmarks

the third batch of queries I ran are delete statements

delete heap/clust where group between 5678910 and 5679410
delete heap/clust where group between 6234567 and 6234967
delete heap/clust where group between 6455429 and 6455729
delete heap/clust where group between 6655429 and 6655729
delete heap/clust where group between 6955429 and 6955729
delete heap/clust where group between 7195542 and 7155729

The result of this benchmark for the heap:

rows  reads CPU   Elapsed 
----- ----- ----- -------- 
1503  10630 62ms  179ms
401   2838  0ms   26ms
2700  19077 47ms  87ms
0     4     0ms   0ms
2953  20865 62ms  196ms
0     4     0ms   9ms

Update on 9 Mar 2011:
cmd.CommandText = "delete heap where group between @id and @id+1000";

  • 724 Rows have > 0 CPU and affect more than 0 rows
Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts     192      69788    4781         -
Cpu            15        499      45   0.01247
Reads         841     307958   20987   4.37880
Writes          2       1819     127   0.02648
Duration   0.3775  1534.3383 17.2412   0.00349

End of Update on 9 Mar 2011.


the result of this benchmark for the clust:

rows  reads CPU   Elapsed 
----- ----- ----- -------- 
1503  9228  16ms  55ms
401   3681  0ms   50ms
2700  24644 46ms  79ms
0     3     0ms   0ms
2953  26955 47ms  92ms
0     3     0ms   0ms

Update on 9 Mar 2011:

cmd.CommandText = "delete clust where group between @id and @id+1000";

  • 751 Rows have > 0 CPU and affect more than 0 rows
Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts     144      69788    4648         -
Cpu            15        764      56   0.01538
Reads         989     458467   30207   6.48490
Writes          2       1830     127   0.02694
Duration   0.2938  2512.1968 24.3714   0.00555

End of Update on 9 Mar 2011.


INSERT benchmarks

The last part of the benchmark is the execution of insert statements.

insert into heap/clust (...)
values (...),
(...),
(...),
(...),
(...),
(...)


The result of this benchmark for the heap:

rows  reads CPU   Elapsed 
----- ----- ----- -------- 
6     38    0ms   31ms

Update on 9 Mar 2011:

string str = @"insert into heap (group, currency, year, period, domain_id, mtdAmount, mtdAmount, ytdAmount, amount, ytd_restated, restated, auditDate, auditUser)
                    values";

                    for (int x = 0; x < 999; x++)
                    {
                        str += string.Format(@"(@id + {0}, 'EUR', 2012, 2, 0, 100, 100, 1000 + @id,1000, 1000,1000, current_timestamp, 'test'),  ", x);
                    }
                    str += string.Format(@"(@id, 'CAD', 2012, 2, 0, 100, 100, 1000 + @id,1000, 1000,1000, current_timestamp, 'test') ", 1000);

                    cmd.CommandText = str;
  • 912 statements have > 0 CPU
Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts    1000       1000    1000         -
Cpu            15       2138      25   0.02500
Reads        5212       7069    6328   6.32837
Writes         16         34      22   0.02222
Duration   1.6336   293.2132  4.4009   0.00440

End of Update on 9 Mar 2011.


The result of this benchmark for the clust:

rows  reads CPU   Elapsed 
----- ----- ----- -------- 
6     50    0ms   18ms

Update on 9 Mar 2011:

string str = @"insert into clust (group, currency, year, period, domain_id, mtdAmount, mtdAmount, ytdAmount, amount, ytd_restated, restated, auditDate, auditUser)
                    values";

                    for (int x = 0; x < 999; x++)
                    {
                        str += string.Format(@"(@id + {0}, 'EUR', 2012, 2, 0, 100, 100, 1000 + @id,1000, 1000,1000, current_timestamp, 'test'),  ", x);
                    }
                    str += string.Format(@"(@id, 'CAD', 2012, 2, 0, 100, 100, 1000 + @id,1000, 1000,1000, current_timestamp, 'test') ", 1000);

                    cmd.CommandText = str;
  • 946 statements have > 0 CPU
Counter   Minimum    Maximum Average  Weighted
--------- ------- ---------- ------- ---------
RowCounts    1000       1000    1000         -      
Cpu            15       2403      21   0.02157
Reads        6810       8997    8412   8.41223
Writes         16         25      19   0.01942
Duration   1.5375   268.2571  6.1463   0.00614

End of Update on 9 Mar 2011.


Conclusions

Although there are more logical reads going on when accessing the table with the clustered & the nonclustered index (while using the nonclustered index) the performance results are:

  • SELECT statements are comparable
  • UPDATE statements are faster with a clustered index in place
  • DELETE statements are faster with a clustered index in place
  • INSERT statements are faster with a clustered index in place

Of course my benchmark was very limited on a specific kind of table and with a very limited set of queries, but I think that based on this information we can already start saying that it is virtually always better to create a clustered index on your table.

Update on 9 Mar 2011:

As we can see from the added results, the conclusions on the limited tests were not correct in every case.

Weighted Duration

The results now indicate that the only statements which benefit from the clustered index are the update statements. The other statements are about 30% slower on the table with clustered index.

Some additional charts where I plotted the weighted duration per query for heap vs clust.
Weighted Duration heap vs clustered for Select

Weighted Duration heap vs clustered for Join

Weighted Duration heap vs clustered for Update

Weighted Duration heap vs clustered for Delete

As you can see the performance profile for the insert statements is quite interesting. The spikes are caused by a few data points which take a lot longer to complete.
Weighted Duration heap vs clustered for Insert

End of Update on 9 Mar 2011.

萌能量女王 2024-10-26 06:23:54

正如索引女王 Kimberly Tripp 在她的博客文章集群中很好地解释的那样索引争论仍在继续...,数据库表上有一个集群键几乎可以加快所有操作的速度,而不仅仅是SELECT

与聚簇表相比,SELECT 在堆上的速度通常较慢,只要您选择一个聚簇键 - 类似于INT IDENTITY。如果您使用非常糟糕的集群键,例如 GUID 或具有大量可变长度组件的复合键,那么,但只有这样,堆可能会更快。但在这种情况下,你确实需要首先清理你的数据库设计......

所以总的来说,我认为堆没有任何意义 - 选择一个好的、有用的集群键,你应该从所有方面受益尊重。

As Kimberly Tripp - the Queen of Indexing - explains quite nicely in her blog post The Clustered Index Debate continues..., having a clustering key on a database table pretty much speeds up all operations - not just SELECT.

SELECT are generally slower on a heap as compared to a clustered table, as long as you pick a good clustering key - something like an INT IDENTITY. If you use a really really bad clustering key, like a GUID or a compound key with lots of variable length components, then, but only then, a heap might be faster. But in that case, you really need to clean up your database design in the first place...

So in general, I don't think there's any point in a heap - pick a good, useful clustering key and you should benefit in all respects.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文