将行非规范化为列是不是会提高 SQL Server 中的性能?

Posted

技术标签:

【中文标题】将行非规范化为列是不是会提高 SQL Server 中的性能?【英文标题】:Does denormalizing rows to columns enhance performance in SQL Server?将行非规范化为列是否会提高 SQL Server 中的性能? 【发布时间】:2013-05-08 04:47:41 【问题描述】:

我的数据是整数值矩阵,表示带状分布曲线。 我正在优化 SELECT 性能而不是 INSERT 性能。最多有 100 个波段。 我将主要通过对一段时间内的波段求和或平均来查询这些数据。

我的问题是,我是否可以通过将这些数据展平到一个表中(每个波段有 1 列)或使用表示波段值的单列来实现更好的性能

扁平化数据

UserId ActivityId DateValue Band1 Band2 Band3....Band100
10001  10002      1/1/2013  1     5     100      200

或归一化

UserId ActivityId DateValue Band BandValue
10001  10002      1/1/2013  1    1
10001  10002      1/1/2013  2    5
10001  10002      1/1/2013  3    100

示例查询

SELECT AVG(Band1), AVG(Band2), AVG(Band3)...AVG(Band100)
FROM ActivityBands
GROUP BY UserId
WHERE DateValue > '1/1/2012' AND DateValue < '1/1/2013'

【问题讨论】:

【参考方案1】:

以标准化格式存储数据。

如果您无法从该方案中获得可接受的性能,请先考虑表上的索引,而不是反规范化。您可能缺少一个索引,该索引会使其执行类似于非规范化表。接下来,尝试编写一个查询以从规范化表中检索数据,以使结果集看起来像非规范化表,并使用该查询创建一个indexed view。这将为您提供与非规范化表相同的选择性能,但保留适当规范化的良好数据组织优势。

【讨论】:

【参考方案2】:

非规范化只优化了一种访问数据的方式,而牺牲了(几乎所有)其他方式。

如果您只有一种对性能至关重要的访问方法,非规范化可能会有所帮助;尽管适当的索引选择有更大的好处。但是,如果您对数据有多个性能关键的访问路径,则最好寻求其他优化。

创建适当的聚集索引;将您的非聚集索引放在 SSD 上。增加服务器上的内存;所有技术都可以提高所有*访问的性能,而不是在各种访问之间进行权衡。

【讨论】:

【参考方案3】:

如果您要访问每行中的所有(或大部分)波段,那么非规范化形式会更好。以我的经验来说要好得多。

原因很简单。页面中数据的大小要小得多,因此需要读取的页面要少得多才能满足查询。每行存储一个波段的开销约为 4 个整数或 32 个字节。所以,100 个波段大约是 3200 字节。在单个记录中,记录大小为 100*4+8 或大约 408 字节。如果您的查询正在读取大量记录,这会显着降低 I/O 需求。

有一个警告。如果您只阅读一条记录,那么 100 条记录适合在 SQL 中的单个页面上,而一条记录适合在单个页面上。在这两种情况下,单页读取的 I/O 可能相同。好处是您阅读的数据越来越多。

您的示例查询正在读取数百或数千行,因此非规范化应该有利于这样的查询。

【讨论】:

【参考方案4】:

如果您想非常快速地获取数据,那么您应该展平表格并使用索引来改进与您建议的类似的广泛列范围的选择。但是,如果您对构建数据以进行快速更新感兴趣,那么将 3 级或 4 级规范化与大量表连接结合使用应该会提供更好的性能。

【讨论】:

以上是关于将行非规范化为列是不是会提高 SQL Server 中的性能?的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL Server 2012 中使用 Pivot 函数将行数据更改为列

如何将行旋转为列,并按过去 7 天显示 - SQL SERVER

SQL Server 2008 R2,将列转换为行,将行转换为列[重复]

试图将行扁平化为列

SQL Server - Pivot 将行转换为列(带有额外的行数据)

SQL Server JSON 将行转置为列