小编Ale*_*min的帖子

LOB_DATA、慢表扫描和一些 I/O 问题

我有一个相当大的表,其中一列是 XML 数据,XML 条目的平均大小约为 15 KB。所有其他列都是常规整数、大整数、GUID 等。为了获得一些具体数字,假设该表有一百万行,大小约为 15 GB。

我注意到的是,如果我想选择所有列,这个表选择数据的速度真的很慢。当我做

SELECT TOP 1000 * FROM TABLE
Run Code Online (Sandbox Code Playgroud)

从磁盘读取数据大约需要 20-25 秒 - 即使我没有对结果强加任何排序。我使用冷缓存(即 after DBCC DROPCLEANBUFFERS)运行查询。IO统计结果如下:

扫描计数 1,逻辑读 364,物理读 24,预读 7191,lob 逻辑读 7924,lob 物理读 1690,lob 预读 3968。

它抓取了大约 15 MB 的数据。执行计划如我所料显示聚集索引扫描。

除了我的查询外,磁盘上没有任何 IO;我还检查了聚集索引碎片是否接近 0%。这是一个消费级 SATA 驱动器,但我仍然认为 SQL Server 能够以比 ~100-150 MB/min 更快的速度扫描表。

XML 字段的存在导致大部分表数据位于 LOB_DATA 页上(实际上约 90% 的表页是 LOB_DATA)。

我想我的问题是 - 我认为 LOB_DATA 页面会导致扫描缓慢不仅是因为它们的大小,还因为当表中有很多 LOB_DATA 页面时,SQL Server 无法有效扫描聚集索引,我是否正确?

更广泛地说 - 拥有这样的表结构/数据模式是否合理?使用 Filestream 的建议通常说明更大的字段大小,所以我真的不想走那条路。我还没有真正找到关于这个特定场景的任何好的信息。

我一直在考虑 XML 压缩,但它需要在客户端或使用 SQLCLR 完成,并且需要在系统中实现相当多的工作。

我尝试了压缩,因为 XML 是高度冗余的,所以我可以(在 …

performance xml sql-server blob

19
推荐指数
2
解决办法
2901
查看次数

当我添加连接提示时,为什么 SQL Server 行估计会发生变化?

我有一个查询,它连接了几个表并且执行得非常糟糕 - 行估计偏离了(1000 次)并且选择了嵌套循环连接,从而导致多个表扫描。查询的形状相当简单,看起来像这样:

SELECT t1.id
FROM t1
INNER JOIN t2 ON t1.id = t2.t1_id
LEFT OUTER JOIN t3 ON t2.id = t3.t2_id
LEFT OUTER JOIN t4 ON t3.t4_id = t4.id 
WHERE t4.id = some_GUID
Run Code Online (Sandbox Code Playgroud)

玩弄查询时,我注意到当我提示它对其中一个连接使用合并连接时,它的运行速度要快很多倍。这我可以理解 - 合并连接是连接数据的更好选择,但 SQL Server 只是没有正确选择嵌套循环。

我不完全理解的是为什么这个连接提示会改变所有计划运营商的所有估计?通过阅读不同的文章和书籍,我假设基数估计是在构建计划之前执行的,因此使用提示不会改变估计,而是明确告诉 SQL Server 使用特定的物理连接实现。

然而,我看到的是合并提示使所有估计变得非常完美。为什么会发生这种情况,是否有任何通用技术可以使查询优化器在没有提示的情况下做出更好的估计 - 考虑到统计数据显然允许这样做?

UPD:匿名执行计划可以在这里找到:https ://www.dropbox.com/s/hchfuru35qqj89s/merge_join.sqlplan?dl =0 https://www.dropbox.com/s/38sjtv0t7vjjfdp/no_hints_join.sqlplan?dl =0

我使用 TF 3604、9292 和 9204 检查了这两个查询使用的统计数据,它们是相同的。然而,被扫描/搜索的索引在查询之间是不同的。

除此之外,我尝试运行查询OPTION (FORCE ORDER)- 它比使用合并联接运行得更快,为每个联接选择 HASH MATCH。

performance sql-server optimization t-sql performance-tuning

16
推荐指数
1
解决办法
584
查看次数

已提交读隔离下的缺失行

众所周知,Read Committed 隔离容易出现不同的异常。我阅读了伟大的保罗怀特关于隔离级别的系列。与讨论相关的帖子是这个:

它声明(再次,这是众所周知的),在读提交隔离下运行的语句:

Can encounter the same row multiple times;
Can miss some rows completely;
Run Code Online (Sandbox Code Playgroud)

我的问题是关于“缺失行”部分。讨论缺失行的示例通常使用以下查询来演示问题:

select count(*) from table.

我的问题是在“常规”选择查询中可以遗漏行吗?意思是,可以像这样的查询

select * from table

甚至

select * from table where id = @id

还会错过在该查询开始之前提交的行吗?此问题仅适用于使用锁定(而非 RCSI)提交的读取,因为 RCSI 不允许这些类型的异常。

sql-server concurrency isolation-level

7
推荐指数
1
解决办法
234
查看次数