在使用集群复合键对表进行“大”插入期间会发生什么?


8

我的SQL知识是有限的,因此我将使用的术语很可能不是正确的术语。

我有一个表,用于存储多个位置的测试结果。

测试将记录在不同位置(没有网络连接)的不同数据库中,并且“主”位置将定期从其他位置“导入”测试结果。

我计划在LocationId(int)和Date(datetime)列上按此顺序有一个集群复合主键。原因是它应该将一个位置的所有结果保持在一起,并且我几乎永远不会按日期范围进行查询,而是按日期范围和位置进行查询。

行大小为80到100个字节,测试结果的数量不应超过几百万。典型的“导入”将从另一个位置插入50到10万个结果。

进口期间会发生什么?SQL是否会“移动”现有行以维护集群,还是会让表变得“碎片化”?如果一次完成一行导入,是否会对性能造成重大影响?我是否应该只是不理会行的顺序,而只是添加一个Identity列作为主键,并在Date列上添加一个索引来帮助查询?

Answers:


19

天哪,您在这里有很多问题。让我们分解一下。

问:SQL是否会“移动”现有行以维持群集,还是会让表“碎片化”?

将数据库想像成页面的集合-桌上摆放的文字纸。现在考虑一下字典。如果您想向词典中添加更多单词,则可以在页面上有空白时将它们添加到位。

刚开始使用空字典时,这相对容易。但是考虑一下其中有成千上万纸页的成熟词典。

当您想向该成熟词典中添加更多单词时,很可能页面上将没有任何空间。SQL Server将“撕裂”页面-它会将一个崭新的页面带到其他地方,并将某些单词移到该新页面上。新页面将在字典的末尾。好消息是,执行完此操作后,字典的末尾以及中间都有一个半空的页面,两个页面都有空格添加单词。

如果您恰好按此顺序添加它们,那就是。(这就是为什么加载数据的方式变得越来越重要的原因。)

如果一次完成一行导入,是否会对性能造成重大影响?

忘记一秒钟的索引-不管索引结构如何,一次只添加一行数据都是毫无效率的。SQL Server是一个基于集合的系统-只要您可以按集合工作,就应该这样做。

查询数据时会怎样?

你没有问这个,但我是在问你,哈哈哈。

回想一下我们插入物的后果。现在,我们有了一个字典,该字典大部分都是有序的,但是当您到达字典的几个要点时,您将不得不跳到后面以从其他几页中读取。如果这些页全部都缓存在内存(RAM,缓冲池等)中,那么开销不会那么大。无论如何,大多数内存访问都是随机的-这与SQL Server不会将字典按顺序存储在内存中不同。

另一方面,如果您需要从常规的磁性硬盘驱动器中获取数据(旋转锈蚀),那么如果按顺序存储数据,最终会获得一些性能上的好处。但是,这里真正的设计目标是从RAM中获取数据,而不是从驱动器中获取数据。磁盘上的碎片整理数据与磁盘上的碎片数据之间的区别远不及从磁盘上获取碎片与从RAM上获取碎片之间的差异那么大

我是否应该只是不理会行的顺序,而只是添加一个Identity列作为主键,并在Date列上添加一个索引来帮助查询?

宾果游戏:这是物理数据库设计和逻辑数据库设计之间的区别。最初,程序员必须担心物理数据库的设计,但是只要您的数据库的大小(例如100GB)以下,就可以在后期修复逻辑设计。在此处放置一个标识字段供初学者使用,在该字段上进行群集,然后使用几个月,然后重新访问索引设计以最大化性能。

话虽如此,一旦您对这种类型的决策有经验,那么您将可以更好地从一开始就猜测指标。即便如此,我最初通常甚至没有对索引设计投入太多的思考。用户似乎从未以我期望的方式查询数据。


1
一个接一个的插入是一个理论问题。在性能方面,对我来说似乎是可疑的,就像您在大多数地方所读到的那样,“行实际上以与聚簇索引相同的顺序存储在磁盘上”。
萨莎K

我去找身分专栏。数据将在“末尾”添加,并自然按日期排序。不同地点的相同日期不会“靠得很近”,但这对我来说根本不重要。
萨沙K
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.