SQL 服务器性能:50 列对比单列 binary/varbinary
SQL Server performance: 50 columns vs single binary/varbinary
是否可以通过将 50 float
列替换为单个 binary(n)
(n
来提高 SQL Server 2008 R2(和更新版本)的插入性能是 50 x 4)?
我会假设使用固定大小binary(n)
应该会提高性能(数据量相同,处理所有列所需的工作更少并且更短SQL 查询),但许多网站建议不要使用 binary
列,所以我想看看使用这个是否真的有问题?
此外,问题是 table 相当非规范化,通常并非所有列都填充了值,因此 varbinary(n)
在许多情况下允许我减少行大小。有时只填充一列,但平均约 10 列。
然后第三个问题是,如何更进一步并用单个 varbinary(5*50*4)
替换(比如说)5 行 x 50 float32
列?
因此,深入了解以下内容会很酷:
- 将 1 行 50
float
列替换为单个 binary(200)
;
- 将 50 x
float
的 1 行替换为单个 varbinary(204)
(flags/length 信息的几个字节)- 在未使用列时保存 space;
- 用单个
varbinary(1024)
替换 5 行 50 x float
(flags/length 信息的几个字节)。
在所有情况下总是一次读取整行。
(更新)
澄清一下,存储的数据是:
Timestamp_rounded Value_0ms Value_20ms Value_40ms ... Value_980ms
2016-01-10 10:00:00 10.0 11.1 10.5 ... 10.5
我总是读取整行,主聚集键是第一列(时间戳),我永远不必通过任何其他列查询 table。
规范化数据显然有一个 Timestamp
/Value
对,其中 Timestamp
将具有毫秒精度。但是我将不得不存储 50 行两列,而不是 1 行 (Timestamp
+ BLOB
).
这是一个糟糕的想法。拥有 4 字节的 50 列与拥有 200 字节的一列相比,任何优化这 50 列中的任何列的查询的希望都破灭了。首先,从 'classic' SQL 服务器 pov:
- 您消除了下推谓词和扫描时间过滤
- 您消除了建立索引的可能性
- 您消除了数据纯度检查(对浮点数尤其重要,因为并非所有位模式都能生成有效的浮点数!)
- 您消除了基于列统计的成本优化
随着你走得更多 'modern' 并开始考虑 SQL 服务器更新选项:
- 您消除了 in-row compression 个选项
- 您消除了 columnar storage 个选项
- 您消除了内存存储优化
所有这些甚至都没有考虑您对试图查询数据的同胞造成的痛苦。
the issue is that the table is rather denormalized, and not all columns are filled with values usually, so varbinary(n) would allow me to reduce the row size in many cases. Sometimes only a single column is filled, but ~10 on average.
然后使用行压缩存储:
ALTER TABLE <your table> REBUILD PARTITION = ALL
WITH (DATA_COMPRESSION = ROW);
如果数据只是追加且很少 updated/deleted 并且大多数查询都是分析性的,那么最好使用列存储。由于 SQL Server 2016 SP1 列存储 are available across every SQL Server edition。
作为实验,我尝试了两种不同的方法来比较它们。
我发现经过一些调整后,二进制版本比 50 col 版本快大约 3 倍。
这个场景非常具体,我的测试只测试了一些非常具体的东西。与我的 test-setup 的任何偏差都会对结果产生影响。
测试是如何进行的
对于 50 col 版本,我有 50 个可为 null 的浮点列,我用 float.MaxValue
.
填充了所有列
对于二进制版本,我只有一个列。该列的值由 50x float.MaxValue + "|"
的字符串构成,全部连接成一个长字符串。然后将字符串转换为 byte[] 以存储在 table.
中
两个 table 都是没有索引或约束的堆。
我的测试代码可以在这里找到https://github.com/PeterHenell/binaryBulkInsertComparison
我 运行 在带有 SSD 驱动器的 6 核工作站上 SQL Server 2014 Developer Edition 上进行了测试。
我知道纯粹主义者会讨厌这种方法,但如果您的用例真的那么有限,那么单列样式当然会更快。
但是,老实说,如果就这么简单,那么您将获得更高的性能 writing/querying 直接使用简单的固定宽度格式的单个文件,那么任何数据库都可以提供。备份、安全等功能都可以在文件级别完成。
例如,有一个 jdbc csv 文件驱动程序可以让您的文件看起来像一个 SQL 连接,如果您仍然想要一个 SQL 像 API。我敢肯定,无论您使用什么进行编程,都存在其他方法。提示恐怖的喘息声!
另请注意,有许多数据库技术。有些针对插入性能进行了优化,而不是其他。
听起来你有类似传感器数据的东西,而你的列实际上更像是一个矩阵,也许具有空间意义。在那种情况下,您可能希望查看为该数据格式明确编码的数据库技术。 SciDB 就是这样一种数据库。它部分是由从事 Vertica 工作的同一个人设计的,所以我希望它具有相当不错的摄取性能。
是否可以通过将 50 float
列替换为单个 binary(n)
(n
来提高 SQL Server 2008 R2(和更新版本)的插入性能是 50 x 4)?
我会假设使用固定大小binary(n)
应该会提高性能(数据量相同,处理所有列所需的工作更少并且更短SQL 查询),但许多网站建议不要使用 binary
列,所以我想看看使用这个是否真的有问题?
此外,问题是 table 相当非规范化,通常并非所有列都填充了值,因此 varbinary(n)
在许多情况下允许我减少行大小。有时只填充一列,但平均约 10 列。
然后第三个问题是,如何更进一步并用单个 varbinary(5*50*4)
替换(比如说)5 行 x 50 float32
列?
因此,深入了解以下内容会很酷:
- 将 1 行 50
float
列替换为单个binary(200)
; - 将 50 x
float
的 1 行替换为单个varbinary(204)
(flags/length 信息的几个字节)- 在未使用列时保存 space; - 用单个
varbinary(1024)
替换 5 行 50 xfloat
(flags/length 信息的几个字节)。
在所有情况下总是一次读取整行。
(更新)
澄清一下,存储的数据是:
Timestamp_rounded Value_0ms Value_20ms Value_40ms ... Value_980ms
2016-01-10 10:00:00 10.0 11.1 10.5 ... 10.5
我总是读取整行,主聚集键是第一列(时间戳),我永远不必通过任何其他列查询 table。
规范化数据显然有一个 Timestamp
/Value
对,其中 Timestamp
将具有毫秒精度。但是我将不得不存储 50 行两列,而不是 1 行 (Timestamp
+ BLOB
).
这是一个糟糕的想法。拥有 4 字节的 50 列与拥有 200 字节的一列相比,任何优化这 50 列中的任何列的查询的希望都破灭了。首先,从 'classic' SQL 服务器 pov:
- 您消除了下推谓词和扫描时间过滤
- 您消除了建立索引的可能性
- 您消除了数据纯度检查(对浮点数尤其重要,因为并非所有位模式都能生成有效的浮点数!)
- 您消除了基于列统计的成本优化
随着你走得更多 'modern' 并开始考虑 SQL 服务器更新选项:
- 您消除了 in-row compression 个选项
- 您消除了 columnar storage 个选项
- 您消除了内存存储优化
所有这些甚至都没有考虑您对试图查询数据的同胞造成的痛苦。
the issue is that the table is rather denormalized, and not all columns are filled with values usually, so varbinary(n) would allow me to reduce the row size in many cases. Sometimes only a single column is filled, but ~10 on average.
然后使用行压缩存储:
ALTER TABLE <your table> REBUILD PARTITION = ALL
WITH (DATA_COMPRESSION = ROW);
如果数据只是追加且很少 updated/deleted 并且大多数查询都是分析性的,那么最好使用列存储。由于 SQL Server 2016 SP1 列存储 are available across every SQL Server edition。
作为实验,我尝试了两种不同的方法来比较它们。
我发现经过一些调整后,二进制版本比 50 col 版本快大约 3 倍。
这个场景非常具体,我的测试只测试了一些非常具体的东西。与我的 test-setup 的任何偏差都会对结果产生影响。
测试是如何进行的
对于 50 col 版本,我有 50 个可为 null 的浮点列,我用 float.MaxValue
.
对于二进制版本,我只有一个列。该列的值由 50x float.MaxValue + "|"
的字符串构成,全部连接成一个长字符串。然后将字符串转换为 byte[] 以存储在 table.
两个 table 都是没有索引或约束的堆。
我的测试代码可以在这里找到https://github.com/PeterHenell/binaryBulkInsertComparison
我 运行 在带有 SSD 驱动器的 6 核工作站上 SQL Server 2014 Developer Edition 上进行了测试。
我知道纯粹主义者会讨厌这种方法,但如果您的用例真的那么有限,那么单列样式当然会更快。
但是,老实说,如果就这么简单,那么您将获得更高的性能 writing/querying 直接使用简单的固定宽度格式的单个文件,那么任何数据库都可以提供。备份、安全等功能都可以在文件级别完成。
例如,有一个 jdbc csv 文件驱动程序可以让您的文件看起来像一个 SQL 连接,如果您仍然想要一个 SQL 像 API。我敢肯定,无论您使用什么进行编程,都存在其他方法。提示恐怖的喘息声!
另请注意,有许多数据库技术。有些针对插入性能进行了优化,而不是其他。
听起来你有类似传感器数据的东西,而你的列实际上更像是一个矩阵,也许具有空间意义。在那种情况下,您可能希望查看为该数据格式明确编码的数据库技术。 SciDB 就是这样一种数据库。它部分是由从事 Vertica 工作的同一个人设计的,所以我希望它具有相当不错的摄取性能。