为什么 Select SQL 查询带有 blob 的表很慢,即使没有选择 blob?
Why Select SQL queries on tables with blobs are slow, even when the blob is not selected?
SELECT 对包含 BLOB 的表的查询很慢,即使我不包括 BLOB 列也是如此。有人可以解释为什么,也许如何规避它?我正在使用 SQL Server 2012,但也许这更像是一个概念性问题,对于其他发行版也很常见。
我发现这个 post: SQL Server: select on a table that contains a blob,它显示了同样的问题,但是标记的答案没有解释为什么会发生这种情况,也没有提供解决问题的好建议.
然后我得到了一个建议,将所有 blob 放在一个单独的 table 中并带有一个身份 ID,然后只将身份 ID 保存在您的主 table
中
可能是因为 - 也许 SQL 无法轻松缓存 table 页面,您必须更频繁地访问磁盘。虽然我不是专家,但为什么。
很多人对数据库中的 BLOBS/images 皱眉 - 在 SQL 2012 年有一些妥协,您可以配置数据库以将对象保存在文件结构中,而不是在实际中DB 了 - 你可能想找那个
如果您正在寻求一种解决性能拖累的方法,可以采用多种方法。如果您不是简单地选择整个记录集,那么将索引添加到您的 table 应该会有很大帮助。在 table 上创建视图也可能有所帮助。还值得检查 table 上的索引碎片级别,因为这会导致性能不佳,并且可以通过定期维护工作来解决。创建链接 table 来存储 blob 数据的建议也是一个非常好的建议。
但是,如果您的问题是问为什么会这样,那是因为 MS SQL 服务器运行方式的基础。本质上是你的数据库,以及服务器上的所有数据库,并分成页面,8kb 的数据块和 96 字节 header。每个页面代表单个 I/O 操作中可能发生的情况。收集的页面包含并分组在 Exents 中,64kb collections 八个连续页面。 SQL 服务器因此每兆字节数据使用 16 个 Exent。有几种不同的页面类型,例如数据页面类型不会包含所谓的 "Large Objects"。这包括数据类型文本、图像、varbinary(max)、xml 数据等...这些也用于存储超过 8kb 的可变长度列(并且不要忘记 96 字节 header).
每页末尾会有少量免费space。数据库操作显然一直在移动这些页面,并且在处理大量 I/O 和随机记录访问/修改的数据库中,免费 space 分配可以大量增长。这就是为什么数据库上的免费 space 可以大量增长。管理套件中提供了一些工具,可让您减少或删除免费 space 以及基本上 re-organizes 页面和扩展。
现在,我可能会在这里取得飞跃,但我猜测您 table 中的 blob 超过 8kb。请记住,如果它们超过 64kb,它们不仅会跨越多个页面,而且实际上会跨越多个范围。这样做的最终结果是 "normal" table 读取将导致大量 I/O 请求。即使您对 BLOB 数据不感兴趣,服务器也可能必须通读页面和扩展区才能获取其他 table 数据。随着更多事务使构成 table 的页面和扩展变为 non-contiguous.
,这只会变得更加复杂。
在使用 "Large Objects" 的地方,SQL 服务器写入 Row-Overflow 值,其中包括指向数据实际存储位置的 24 位指针。如果您的 table 上有几列超过 8kb 页面大小并受随机事务影响,您会发现服务器所做的大部分工作是 I/O 移动页面的操作进出内存、读取指针、获取关联的行数据等等......所有这些都代表着严重的开销。
SELECT 对包含 BLOB 的表的查询很慢,即使我不包括 BLOB 列也是如此。有人可以解释为什么,也许如何规避它?我正在使用 SQL Server 2012,但也许这更像是一个概念性问题,对于其他发行版也很常见。
我发现这个 post: SQL Server: select on a table that contains a blob,它显示了同样的问题,但是标记的答案没有解释为什么会发生这种情况,也没有提供解决问题的好建议.
然后我得到了一个建议,将所有 blob 放在一个单独的 table 中并带有一个身份 ID,然后只将身份 ID 保存在您的主 table
中可能是因为 - 也许 SQL 无法轻松缓存 table 页面,您必须更频繁地访问磁盘。虽然我不是专家,但为什么。
很多人对数据库中的 BLOBS/images 皱眉 - 在 SQL 2012 年有一些妥协,您可以配置数据库以将对象保存在文件结构中,而不是在实际中DB 了 - 你可能想找那个
如果您正在寻求一种解决性能拖累的方法,可以采用多种方法。如果您不是简单地选择整个记录集,那么将索引添加到您的 table 应该会有很大帮助。在 table 上创建视图也可能有所帮助。还值得检查 table 上的索引碎片级别,因为这会导致性能不佳,并且可以通过定期维护工作来解决。创建链接 table 来存储 blob 数据的建议也是一个非常好的建议。
但是,如果您的问题是问为什么会这样,那是因为 MS SQL 服务器运行方式的基础。本质上是你的数据库,以及服务器上的所有数据库,并分成页面,8kb 的数据块和 96 字节 header。每个页面代表单个 I/O 操作中可能发生的情况。收集的页面包含并分组在 Exents 中,64kb collections 八个连续页面。 SQL 服务器因此每兆字节数据使用 16 个 Exent。有几种不同的页面类型,例如数据页面类型不会包含所谓的 "Large Objects"。这包括数据类型文本、图像、varbinary(max)、xml 数据等...这些也用于存储超过 8kb 的可变长度列(并且不要忘记 96 字节 header).
每页末尾会有少量免费space。数据库操作显然一直在移动这些页面,并且在处理大量 I/O 和随机记录访问/修改的数据库中,免费 space 分配可以大量增长。这就是为什么数据库上的免费 space 可以大量增长。管理套件中提供了一些工具,可让您减少或删除免费 space 以及基本上 re-organizes 页面和扩展。
现在,我可能会在这里取得飞跃,但我猜测您 table 中的 blob 超过 8kb。请记住,如果它们超过 64kb,它们不仅会跨越多个页面,而且实际上会跨越多个范围。这样做的最终结果是 "normal" table 读取将导致大量 I/O 请求。即使您对 BLOB 数据不感兴趣,服务器也可能必须通读页面和扩展区才能获取其他 table 数据。随着更多事务使构成 table 的页面和扩展变为 non-contiguous.
,这只会变得更加复杂。在使用 "Large Objects" 的地方,SQL 服务器写入 Row-Overflow 值,其中包括指向数据实际存储位置的 24 位指针。如果您的 table 上有几列超过 8kb 页面大小并受随机事务影响,您会发现服务器所做的大部分工作是 I/O 移动页面的操作进出内存、读取指针、获取关联的行数据等等......所有这些都代表着严重的开销。