NCCI 中的 Lob 逻辑读取和 lob 预读

Art*_*yan 8 sql-server columnstore sql-server-2017

我有一个具有以下结构的测试表。

CREATE TABLE [dbo].[DW_test](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[CourtCaseID] [int] NOT NULL,
[ActionID] [int] NOT NULL,
PRIMARY KEY CLUSTERED([ID] ASC)
Run Code Online (Sandbox Code Playgroud)

接下来,我使用以下脚本在我的表中填充了大约 4.7 亿条记录。

insert into DW_test
--select count(*)
--from (
select top 1000000 abs(checksum(newid())) % 100000 + 1 a, abs(checksum(newid())) % 10 + 1 b
from sys.all_objects
cross join sys.all_objects a
cross join sys.all_objects b
cross join sys.all_objects c
cross join sys.all_objects d
cross join sys.all_objects e
cross join sys.all_objects f
cross join sys.all_objects g
--) t
GO
Run Code Online (Sandbox Code Playgroud)

该脚本执行了大约 470 次以在表中生成 4.7 亿条记录并在该表上创建 NCCI。

CREATE NONCLUSTERED COLUMNSTORE INDEX [IX_test1] ON [dbo].[DW_test]
(
    [CourtCaseID],
    [ActionID]
)
Run Code Online (Sandbox Code Playgroud)

接下来我测试简单查询以计算表中的记录数。

DBCC DROPCLEANBUFFERS
GO
select COUNT_BIG(*)
from DW_test 
Run Code Online (Sandbox Code Playgroud)

如果我转,SET STATISTICS IO ON我会得到以下结果

带冷缓存

表'DW_test'。扫描计数 25,逻辑读 3,物理读 0,预读 0,lob 逻辑读 469697,lob 物理读 1,lob 预读 1877324。

表'DW_test'。段读取 453,段跳过 0。

表“工作台”。扫描计数 0,逻辑读 0,物理读 0,预读 0,lob 逻辑读 0,lob 物理读 0,lob 预读 0。

带热缓存

表'DW_test'。扫描计数 25,逻辑读取 3,物理读取 0,预读读取 0,lob 逻辑读取 229248,lob 物理读取 0,lob 预读读取 0。

表'DW_test'。段读取 453,段跳过 0。

表“工作台”。扫描计数 0,逻辑读取 0,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。`

我知道 1 次逻辑读取是在查询执行期间从缓冲池读取的单个数据页,而 1 次物理读取是从磁盘读取的单个数据页。RedGate 告诉我们预读是:

这个数字告诉我们有多少物理读取被 SQL Server 的“预读”机制满足。这与物理读取直接相关,因此如果没有物理读取,则预读读取将为 0。

就我而言,我正在处理 lob 逻辑、物理和预读。我想了解这个数字在我的特殊情况下意味着什么。

如果表有大约 4.7 亿条记录,怎么可能只有 1 lob 物理读取和冷缓存?

lob 页面的总数怎么可能从冷缓存中的大约 230 万个减少到热缓存中的大约 22 万个?

Pau*_*ite 13

如果表有大约 4.7 亿条记录,怎么可能只有 1 lob 物理读取和冷缓存?

有 1 个 LOB 物理读取和 1,877,324 次预读。预读仍然是物理读取,只是提前执行(预取)。Redgate 的引用是不正确的。

lob 页面的总数怎么可能从冷缓存中的大约 230 万个减少到热缓存中的大约 22 万个?

逻辑读取计算内存中页面被触摸的次数。减少是从 469,697(冷缓存)到 229,248(暖缓存)。我对此没有完整的解释,但这可能部分是因为列存储数据连续缓存在单独的列存储对象池中,而不是一般的页面大小的缓冲池。

预读从 b 树的上层读取页面以识别要在扫描之前读取的页面,这也可能导致不同数量的“额外”逻辑读取,具体取决于时间和存储系统的特性. 列存储索引在持久存储上具有 b 树结构。

另一个因素是并行性(似乎您的测试是在 DOP 24 下运行的),因为来自不同线程的重叠请求会导致额外的逻辑读取。如果您使用OPTION (MAXDOP 1).

列存储的内部存储细节没有很好的文档记录,也没有得到通常的 DMV 的完全支持。在这个阶段,我认为冷和热缓存情况下读取减少的最好解释是磁盘和内存(缓存)存储之间的差异。

列存储数据(字典和段)存储在磁盘上的 LOB 中,但出于性能原因而不以相同的格式保存在内存中。因为它们是不同的东西,所以不能仅仅将逻辑读取添加到物理读取中以获得有意义的结果。

  • 没关系。我已经给出了我目前所能给出的最好的答案,所以我会就此搁笔。 (3认同)

Tib*_*szi 2

“如果表有大约 4.7 亿条记录,怎么可能只有 1 lob 物理读取和冷缓存?”

因为其他物理读取是由预读(LOB 类型)提供的。也许 RedGate 的文章让您感到困惑,但是如果您将某个范围(例如)作为预读 (RA),那么您将不会看到任何物理读取。收集物理读取统计信息的线程在缓存中找到了这些页面,因此它们没有累积到物理读取计数器中。

我们遇到的另一种情况是经典的缓冲区高速缓存命中率 perfmon 计数器。RA 读取不会影响此值,因此您可能有大量物理 I/O,但 BCHR 中的值仍接近 100。

“lob 页总数怎么可能从冷缓存中的约 230 万减少到热缓存中的约 220k?”

我的猜测是第一个启动了自动创建统计数据。