在查询中使用列存储索引时,SQL Server 能够使用批处理模式。关于什么可以在批处理模式下运行,什么不能运行的文档很少。请查看以下(激励性)查询计划,其中以批处理模式(绿色)执行的事情数量惊人:
(这是一个估计的计划,我用实际计划来验证实际执行方式确实是批处理。)
请注意,只有 T1 的构建端使用列存储索引。所有探测输入(T2 和 T3)都是行存储。他们的数据似乎过渡到批处理模式。我一直认为批处理模式仅用于通过探针端运行的数据流。
即使数据不是来自列存储索引,数据似乎也可以转换为批处理模式。这就提出了一个问题:为什么 SQL Server 不对仅行存储的查询使用批处理模式?可能对他们中的一些人有益。使用列存储索引是否是使 SQL Server 考虑批处理模式所必需的正式要求?我们可以添加一个带有列存储索引的零行虚拟表来引入批处理模式并实现性能提升吗?
从 SQL Server 2014 开始,究竟可以在批处理模式下运行什么?
我有以下形式的查询:
SELECT ...
FROM ColumnstoreTable cs
CROSS APPLY (
SELECT *
FROM (VALUES
('A', cs.DataA)
, ('B', cs.DataB)
, ('C', cs.DataC)
) x(Col0, Col1)
) someValues
Run Code Online (Sandbox Code Playgroud)
这从 Columnstore 支持的子查询 ( ColumnstoreTable
) 中获取每一行并将这些行相乘。这本质上是一个UNPIVOT
. 真正的查询比这更大。这部分查询会进入其他处理。
这里的问题是这CROSS APPLY
是作为一个循环连接实现的,这是一个合理的选择。不幸的是,循环连接不支持批处理模式。
这部分查询对性能非常关键,我怀疑以批处理模式运行它可能对性能非常有益。
我怎样才能重写这个查询,这样我就不会退出批处理模式?
我确实尝试使用临时表而不是VALUES
,但这并没有改变这样一个事实,即没有相等连接条件来进行哈希连接。
以下查询SUM
对列存储表执行窗口化处理1500 total rows
,每个表的值为 0 或 1,并溢出INT
数据类型。为什么会这样?
SELECT a, p, s, v, m, n,
SUM(CASE WHEN n IS NULL THEN 0 ELSE 1 END)
OVER (PARTITION BY s, v, a ORDER BY p) AS lastNonNullPartition
FROM (
SELECT a, p, s, v, m, n,
RANK() OVER (PARTITION BY v, s, a, p ORDER BY m) AS rank
FROM #t /* A columnstore table with 1,500 rows */
) x
WHERE x.rank = 1
--Msg 8115, …
Run Code Online (Sandbox Code Playgroud) sql-server columnstore window-functions batch-mode sql-server-2016
一个大查询正在运行。溢出到磁盘的批处理模式散列连接的结果使用 流式传输到临时表中select into
。该查询显示等待类型HTDELETE
和HTREPARTITION
偶然。查询未使用列存储索引。
我很确定这些等待类型对于溢出到磁盘的批处理模式散列连接来说是正常的。出于好奇,我试图了解这些等待类型的含义。也许这种洞察力可以帮助优化查询或发现问题。那么这些等待类型是什么意思,在什么情况下它们是预期的呢?
没有列存储索引。我正在使用该left join ZeroRowCsTable on 0=1
技巧为行模式表启用批处理模式。