SQL Server使用和不使用主键插入性能

Eri*_*ric 13 sql-server

简介:我通过以下方式填充了一个表:

insert into the_table (...) select ... from some_other_table
Run Code Online (Sandbox Code Playgroud)

运行上述查询没有上the_table主键是15倍〜比运行速度更快一个主键,我不明白为什么.

细节:我认为最好通过代码示例来解释.

我有一张桌子:

create table the_table (
    a int not null,
    b smallint not null,
    c tinyint not null
);
Run Code Online (Sandbox Code Playgroud)

如果我添加主键,则此插入查询非常慢:

alter table the_table
    add constraint PK_the_table primary key(a, b);

-- Inserting ~880,000 rows
insert into the_table (a,b,c)
    select a,b,c from some_view;
Run Code Online (Sandbox Code Playgroud)

没有主键,相同的插入查询大约快15倍.但是,在没有主键填充the_table之后,我可以添加主键约束,这只需要几秒钟.这个对我来说真的没有意义.

更多信息:

  • 估计的执行计划显示在聚簇索引插入上花费的总查询时间为0%
  • SQL Server 2008 R2开发人员版,10.50.1600

有任何想法吗?

小智 6

实际上它并不像Ryk所暗示的那样明确.

实际上,将数据添加到具有索引的表中然后在堆中更快.

阅读这篇论文 - 据我所知,它得到了很好的认可:

http://www.sqlskills.com/blogs/kimberly/post/The-Clustered-Index-Debate-Continues.aspx

请记住它由SQL Server MVP和Microsoft区域主管编写.

与堆相比,嵌入在集群表中更快(但仅在"右"聚簇表中).这里的主要问题是IAM/PFS中用于确定堆中插入位置的查找比群集表(其中插入位置已知,由群集键定义)慢.插入到定义了顺序(CL)的表中以及该顺序不断增加的位置时,插入更快.我有一些简单的数字,但我正在考虑创建一个更大/更复杂的场景并发布它们.在笔记本电脑上进行简单/快速测试并不总是"令人兴奋".


Ryk*_*Ryk -11

这是一个好问题,但也是一个相当蹩脚的问题。在你问为什么索引会减慢插入速度之前,你知道什么是索引吗?

如果没有,我建议你仔细阅读。聚集索引是一棵 B 树(平衡树),因此每次插入都必须 .... 等待它 .... 平衡树。因此,集群插入比堆上插入慢。如果您不知道堆是什么,那么我建议您停止使用 SQL Server,直到您了解基础知识。否则,您尝试使用一种您不知道自己在做什么的产品,基本上是在高速公路上驾驶卡车,蒙住眼睛,以为自己在骑自行车。意想不到的结果...

因此,当您在填充表后创建聚集索引时,您的“堆”有一些统计信息可供使用,并且 SQL 基本上可以优化一些东西。这个过程比这复杂得多,但在某些情况下,您会发现事后创建聚集索引可能比简单地插入要慢得多。这与键类型、列数、列类型等有关。不幸的是,这不是一个适合答案的主题,这更像是一门完整的课程,而且本身很少有书籍。查看上面的表格,这是一个非常简单的表格,有约 7 字节的行。在这种情况下,插入后创建索引会更快,但插入一些 varchar(250) 等,情况就会发生变化。

如果您不知道,聚集索引(如果您的表有一个)就是您的表。

希望这可以帮助。

  • 否决这个答案是因为我觉得没有必要说“如果你不知道堆是什么,那么我建议停止使用 SQL Server,直到你了解基础知识”。这实在是有点太严厉了。每个人都是从初学者开始的。 (45认同)