我有一个过程可以在数百个数据库中动态运行查询,这些数据库都具有相同的确切架构,并将结果聚合到一个临时表中。该查询仅涉及 3 个表(每个表在数百万行的 10 到 100 之间,但我总共只提取了大约 50,000 行数据)。
查看查询的聚合 IO 统计信息(通过 StatisticsParser.com - 喊出 Richie Rump)时,它显示创建了一个工作表,并且工作表上大约有 550,000 个 LOB 逻辑读取。查询中所有表的常规逻辑读取总数略低于大约 400,000 逻辑读取。
查询中的实际表都没有使用任何 LOB 数据类型,那么这到底是什么意思,它是我查询中瓶颈的潜在来源吗?
(顺便说一句,我拉回的 50,000 行数据仅相当于大约 3 MB 的数据,但我的查询在第一次运行时需要大约 10 秒才能运行(例如,当表的数据页仍在加载到内存中时) ) 然后在后续运行中不到一半的时间,因此尝试查看我是否可以始终接近 <= 4s 基准,以及这些 LOB 逻辑读取是否与它相关。)
更新:这是一个类似的示例查询(再次查看它,我可能已经找到了 LOB 逻辑读取的来源)。
过程签名: sp_StoredProc_ToGetData(@IdsTable TVP (Id INT)、@StartDate DateTime、@EndDate DateTime)
sp_StoredProc_ToGetData 内部的查询:
SELECT Id
INTO #IdsTableTemp
FROM @IdsTable;
-- This query is ran using dynamic SQL but for the example simplicity this is just the root query itself
SELECT 'SomeConstant' AS Field1, T1.Field2, T1.Field3, T3.Field4, T3.Field5
FROM Table1 AS T1
INNER JOIN Table2 AS T2 -- Linking table between T1 and T3
ON T1.PrimaryKey = T2.PrimaryKey
INNER JOIN Table3 AS T3
ON T2.NonClusteredIndexField = T3.PrimaryKey
WHERE T1.Date >= @StartDate
AND T2.Date < @EndDate
根据您的问题描述:
听起来您遇到了这个问题:执行计划分析:神秘工作表
寻找一个计算标量,它在输出时生成 LOB 数据类型,然后通过预取流入嵌套循环连接。
解决这个问题在很大程度上取决于您的源查询,但是需要做一些事情来将 LOB 数据移过循环连接,或者可能获得不同的连接类型。
它总是最终成为我查看的最后一个地方,但事实证明工作表和高 LOB 逻辑读取是由我以递归方式选择的动态 SQL 变量产生的。
由于 sp_ExecuteSQL 参数的类型必须为 NVARCHAR 并且我使用 MAX 作为大小,这导致在 TempDB 中创建工作表和高 LOB 逻辑读取。
仍然不确定为什么当它只迭代大约 250 次递归时它会是 ~550,000 LOB 逻辑读取,例如:
在任何情况下,将我的动态 SQL 变量从 NVARCHAR(MAX) 更改为 NVARCHAR(4000) 都会从统计信息中删除所有 LOB 逻辑读取。