在具有聚集复合键的表上进行“大”插入时会发生什么?

Sac*_*a K 8 sql-server

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

我有一个表格可以存储多个位置的测试结果。

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

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

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

进口期间会发生什么?SQL 会“移动”现有的行来维持集群,还是会让表变得“碎片化”?如果导入一次完成一行,这会导致性能下降吗?我是否应该不理会行的排序,而只是在日期列上添加一个标识列作为主键和一个索引来帮助我的查询?

Bre*_*zar 19

天啊,你这里有很多问题。让我们分解一下。

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

将数据库视为页面的集合 - 放在桌子上的纸片。现在想想字典。如果您想在字典中添加更多单词,如果页面有空白,您可以将它们添加到位。

当您第一次使用空字典开始时,这相对容易。但是想想一本成熟的字典,里面有成千上万的纸页,都满满的。

当您想在成熟的字典中添加更多单词时,页面上可能没有任何空间。SQL Server 将“撕掉”一个页面——它会在其他地方占据一个全新的页面,并将一些单词移到那个新页面上。新页面将在字典的末尾。好消息是,在执行该操作之后,您的字典末尾和中间现在有一个半空的页面,两者都有空间来添加单词。

如果您碰巧按该顺序添加它们,那就是。(这就是加载数据的方式变得越来越重要的原因。)

如果导入一次完成一行,这会导致性能下降吗?

暂时忘记索引 - 无论索引结构如何,一次添加一行数据都是非常低效的。SQL Server 是一个基于集合的系统——只要你可以在集合中工作,你就应该这样做。

当我查询数据时会发生什么?

不是你问的,我是替你问的,哈哈哈。

回想一下我们插入的后果。现在我们有一本字典,大部分是有序的,但是当你到达字典的几个点时,你必须跳到后面才能阅读其他几页。如果这些页面都缓存在您的内存(RAM、缓冲池等)中,那么开销就不会那么大。无论如何,大多数内存访问都是随机的 - 它不像 SQL Server 将您的字典按顺序存储在内存中。

另一方面,如果您需要从传统的磁性硬盘驱动器(旋转锈蚀)获取数据,那么如果数据按顺序存储,您最终可以获得一些性能优势。不过,这里真正的设计目标是从 RAM 中获取数据,而不是从驱动器中获取数据。磁盘上碎片整理的数据与磁盘上的碎片数据之间的差异远不及从磁盘获取数据与从 RAM 获取数据之间的差异显着。

我是否应该不理会行的排序,而只是在日期列上添加一个标识列作为主键和一个索引来帮助我的查询?

Bingo:这是物理数据库设计和逻辑数据库设计的区别。程序员最初不得不担心物理数据库设计,但是只要您的数据库大小在 100GB 以下,您就可以在后期修复逻辑设计,可以这么说。为初学者放置一个标识字段,在其上进行集群,然后在使用几个月后,重新审视索引设计以最大限度地提高性能。

现在,话虽如此,一旦您对这种类型的决策有了经验,那么您将能够更好地从一开始就猜测指数。即便如此,我最初甚至通常不会在索引设计上花太多心思。用户似乎永远不会以我预期的方式查询数据。