为什么在填充表后为表建立索引时,SQL Server的工作速度更快?
我有一个存储过程,它通过查询将750K记录放入临时表中,这是它的第一个操作。如果在填充之前在临时表上创建索引,则与在填充表后进行索引时相比,该项目的运行时间大约要长两倍。 (索引是单列中的整数,被索引的表仅是两列,每列都是一个整数。)
这对我来说似乎有点差,但是那时我对幕后发生的事情没有最坚定的了解。有人对此有答案吗?
解决方案
回答
这是因为,如果我们插入的数据不是按索引顺序排列,则SQL将不得不拆分页面以为其他行腾出空间,以使它们在逻辑上保持在一起
回答
如果以后要立即大量加载索引,则永远不要在空表上创建索引。
当表上的数据更改时,必须维护索引,因此,可以想象一下,对于表上的每个插入都在重新计算索引(这是一项昂贵的操作)。
首先加载表,并在完成加载后创建索引。
回答
那就是性能差异的原因。
在执行大型数据操作操作之后,我们经常必须更新基础索引。我们可以使用UPDATE STATISTICS [table]语句来实现。
回答
另一个选择是删除并重新创建索引,如果我们要进行大数据插入,则可能会更快地执行插入操作。我们甚至可以将其合并到存储过程中。
如果创建聚集索引,它将影响磁盘上数据的物理排序方式。最好在事实之后添加索引,并让数据库引擎在知道数据的分布方式时对行进行重新排序。
例如,假设我们需要用带编号的砖建造一堵砖墙,以便编号最高的砖位于墙的底部。如果我们只是随机分配砖块,那将是一项艰巨的任务,一次我们将不知道哪个砖块将成为编号最高的砖块,并且我们必须将墙拆除并一遍又一遍地重建它。如果我们将所有砖块排在前面,并且可以组织工作,那么完成该任务会容易得多。
回答
如果我们让数据库引擎了解整个作业,这就是数据库引擎的工作方式,它比每次仅馈送一次作业的效率要高得多。
回答
这是因为每次插入新行时,数据库服务器都必须进行计算。基本上,我们每次都会为表重新编制索引。这似乎不是一个非常昂贵的操作,并且不是,但是当我们将它们中的许多一起执行时,就会开始看到影响。这就是为什么我们通常希望在填充行之后进行索引,因为这将是一次性成本。
这是由于以下事实:当SQL Server使用数据对表进行索引时,它能够在索引列中生成值的准确统计信息。 SQL Server有时会重新计算统计信息,但是当我们执行大量插入时,上次计算统计信息后值的分布可能会改变。
统计信息已过时的事实可以在查询分析器中发现。当我们在某个表上看到扫描的预期行数与实际处理的行数相差很大时。
回答
插入所有数据后,应使用UPDATE STATISTICS重新计算值的分布。此后,不应观察到性能差异。
Given unorderedList = {5, 1,3} orderedList = {1,3,5} add 2 to both lists. unorderedList = {5, 1,3,2} orderedList = {1,2,3,5}
这样想吧。
我们认为更容易添加到哪个列表?
回答
顺便说一句,在加载之前对输入进行排序将为我们带来很大的帮助。
如果在表上有索引,则在向表中添加数据时,SQL Server将必须重新排序表,以在新记录的适当位置腾出空间。如果要添加大量数据,则必须一遍又一遍地对其重新排序。通过仅在加载数据之后创建索引,重新排序仅需要发生一次。
回答
当然,如果我们以索引顺序导入记录,那没什么大不了的。
段落数量不匹配