mus*_*cio 14 sql-server varchar
我是出于好奇而问这个问题的,受到这个问题的启发。
我们知道该VARCHAR(MAX)
值超过8000个字节并不存储在行,但在不同的LOB页。随后检索具有此类值的行需要两个或多个逻辑 IO 操作(实际上,理论上需要多一个)。
我们可以将一VARCHAR(MAX)
列作为INCLUDE
d添加到唯一索引,如链接问题所示。如果此列的值长度超过 8000 字节,这些值是否仍会“内联”存储在索引叶页中,还是也将移动到 LOB 页?
Joe*_*ish 19
超过 8000 字节的值不能“内联”存储。它们存储在 LOB 页上。您可以通过sys.dm_db_index_physical_stats看到这一点。从一个简单的表开始:
USE tempdb;
DROP TABLE IF EXISTS #LOB_FOR_ME;
CREATE TABLE #LOB_FOR_ME (
ID BIGINT,
MAX_VERNON_WAS_HERE VARCHAR(MAX)
);
CREATE INDEX IX ON #LOB_FOR_ME (ID) INCLUDE (MAX_VERNON_WAS_HERE);
Run Code Online (Sandbox Code Playgroud)
现在插入一些行的值占用 8000 字节的VARCHAR(MAX)
列并检查 DMF:
USE tempdb;
INSERT INTO #LOB_FOR_ME
SELECT 1, REPLICATE('Z', 8000)
FROM master..spt_values;
SELECT index_level, index_type_desc, alloc_unit_type_desc, page_count, record_count
FROM sys.dm_db_index_physical_stats(DB_ID(), OBJECT_ID('#LOB_FOR_ME'), 2, NULL , 'DETAILED');
Run Code Online (Sandbox Code Playgroud)
索引中没有 LOB 页:
???????????????????????????????????????????????????????????????????????????????????????
? index_level ? index_type_desc ? alloc_unit_type_desc ? page_count ? record_count ?
???????????????????????????????????????????????????????????????????????????????????????
? 0 ? NONCLUSTERED INDEX ? IN_ROW_DATA ? 2540 ? 2540 ?
? 1 ? NONCLUSTERED INDEX ? IN_ROW_DATA ? 18 ? 2540 ?
? 2 ? NONCLUSTERED INDEX ? IN_ROW_DATA ? 1 ? 18 ?
???????????????????????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
但是,如果我添加具有 8001 个字节的值的行:
USE tempdb;
INSERT INTO #LOB_FOR_ME
SELECT 2, REPLICATE(CAST('Z' AS VARCHAR(MAX)), 8001)
FROM master..spt_values;
SELECT index_level, index_type_desc, alloc_unit_type_desc, page_count, record_count
FROM sys.dm_db_index_physical_stats(DB_ID(), OBJECT_ID('#LOB_FOR_ME'), 2, NULL , 'DETAILED');
Run Code Online (Sandbox Code Playgroud)
现在,我刚插入的每一行的索引中都有 1 个 LOB 页面:
???????????????????????????????????????????????????????????????????????????????????????
? index_level ? index_type_desc ? alloc_unit_type_desc ? page_count ? record_count ?
???????????????????????????????????????????????????????????????????????????????????????
? 0 ? NONCLUSTERED INDEX ? IN_ROW_DATA ? 2556 ? 5080 ?
? 1 ? NONCLUSTERED INDEX ? IN_ROW_DATA ? 18 ? 2556 ?
? 2 ? NONCLUSTERED INDEX ? IN_ROW_DATA ? 1 ? 18 ?
? 0 ? NONCLUSTERED INDEX ? LOB_DATA ? 2540 ? 2540 ?
???????????????????????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
您还可以SET STATISTICS IO ON;
通过正确的查询看到这一点。考虑以下仅查看 8000 字节行的查询:
SELECT SUM(LEN(MAX_VERNON_WAS_HERE))
FROM #LOB_FOR_ME
WHERE ID = 1;
Run Code Online (Sandbox Code Playgroud)
执行结果:
扫描计数1,逻辑读2560,物理读0,预读0,lob逻辑读0,lob物理读0,lob预读0。
如果我改为查询 8001 字节的行:
SELECT SUM(LEN(MAX_VERNON_WAS_HERE))
FROM #LOB_FOR_ME
WHERE ID = 2;
Run Code Online (Sandbox Code Playgroud)
现在我看到 lob 写着:
扫描计数 1,逻辑读 20,物理读 0,预读 0,lob 逻辑读 5080,lob 物理读 0,lob 预读 0。
归档时间: |
|
查看次数: |
3545 次 |
最近记录: |