Blu*_*ppy 37 sql-server primary-key clustered-index sql-server-2008-r2
我有几个具有相同基本结构的非常大的桌子。每个都有一个RowNumber (bigint)和DataDate (date)列。每晚都使用 SQLBulkImport 加载数据,并且永远不会加载“新”数据 - 它是历史记录(SQL Standard,不是 Enterprise,因此没有分区)。
因为每一位数据都需要绑定回其他系统,并且每个RowNumber/DataDate组合都是唯一的,那就是我的主键。
我注意到,由于我在 SSMS 表设计器中定义 PK 的方式,RowNumber列在第一和DataDate第二位。
我还注意到我的碎片总是非常高~99%。
现在,因为每个DataDate只出现一次,我希望索引器每天只添加到页面,但我想知道它是否实际上是基于RowNumber第一个索引,因此必须改变其他所有内容?
Rownumber不是标识列,它是由外部系统生成的 int(遗憾的是)。它在每个 开始时重置DataDate。
示例数据
RowNumber | DataDate | a | b | c.....
1 |2013-08-01| x | y | z
2 |2013-08-01| x | y | z
...
1 |2013-08-02| x | y | z
2 |2013-08-02| x | y | z
...
Run Code Online (Sandbox Code Playgroud)
数据按RowNumber顺序加载,DataDate每次加载一个。
导入过程是 bcp - 我尝试加载到临时表,然后从那里按顺序选择 ( ORDER BY RowNumber, DataDate) 但仍然出现高碎片。
Pau*_*ite 53
PK 索引中的列顺序重要吗?
是的,它确实。
默认情况下,主键约束在 SQL Server 中由唯一聚集索引强制执行。聚集索引定义了表中行的逻辑顺序。可能会添加许多额外的索引页来表示 b 树索引的上层,但聚集索引的最低(叶)层只是数据本身的逻辑顺序。
需要明确的是,页面上的行不一定按聚集索引键顺序物理存储。页面中有一个单独的间接结构,用于存储指向每一行的指针。此结构按聚集索引键排序。此外,每个页面都有一个指针,以聚集索引键顺序指向同一级别的上一页和下一页。
使用聚簇主键时(RowNumber, DataDate),行首先按逻辑排序RowNumber,然后按DataDate- 因此所有行在RowNumber = 1逻辑上分组在一起,然后是行,RowNumber = 2依此类推。
当您添加新数据(RowNumbers从 1 到 n)时,新行在逻辑上属于现有页面,因此 SQL Server 可能需要做很多工作来拆分页面以腾出空间。所有这些活动都会产生大量额外的工作(包括记录更改),但没有任何收益。
拆分页面也从大约 50% 的空白开始,因此过度拆分也会导致页面密度低(每页的行数少于最佳值)。这不仅是从磁盘读取的坏消息(低密度 = 更多页面要读取),低密度页面在缓存时也会占用更多内存空间。
将聚集索引更改为(DataDate, RowNumber) 意味着新数据(可能高于DataDates当前存储的数据)被附加到新页面上聚集索引的逻辑末尾。这将消除拆分页面的不必要开销并导致更快的加载时间。更少的碎片数据也意味着预读活动(在进行中的查询需要它们之前从磁盘读取页面)可以更有效。
如果不出意外,你的查询更容易搜索上DataDate比RowNumber。) 上的聚集索引(DataDate, RowNumber支持DataDate(然后RowNumber)上的索引查找。现有的安排只支持在RowNumber(并且只有那时,也许,在DataDate)上寻找。DataDate一旦主键更改,您很可能能够删除现有的非聚集索引。聚集索引将比它替换的非聚集索引更宽,因此您应该进行测试以确保性能仍然可以接受。
使用 导入新数据时bcp,如果导入文件中的数据按聚集索引键排序(理想情况下为(DataDate, RowNumber)并指定bcp选项,则可能会获得更高的性能:
-h "ORDER(DataDate,RowNumber), TABLOCK"
Run Code Online (Sandbox Code Playgroud)
为了获得最佳数据加载性能,您可能会尝试实现最少记录的插入。有关更多信息,请参阅:
Rem*_*anu 15
是的,顺序很关键。我非常怀疑您是否曾经通过 RowNumber(例如WHERE RowNumber=1)进行查询。绝大多数时间序列是按日期 ( WHERE DataDate BEWEEN @start AND @end)查询的,并且此类查询需要按DataDate.
一般而言,碎片化是一种红鲱鱼。减少碎片化不应该是您的目标,但应该为您的查询建立适当的组织。另外减少碎片是一个很好的想法,但它本身并不是一个目标。如果您有一个与您的工作负载相匹配的正确组织的数据模型(您的查询被正确覆盖),并且您的测量结果显示碎片影响性能,那么我们可以讨论它。
| 归档时间: |
|
| 查看次数: |
11528 次 |
| 最近记录: |