回答:
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);
次に、VARCHAR(MAX)
列に8000バイトの値を持つ行をいくつか挿入し、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');
インデックスに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 ║
╚═════════════╩════════════════════╩══════════════════════╩════════════╩══════════════╝
しかし、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');
これで、挿入したばかりのすべての行のインデックスに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 ║
╚═════════════╩════════════════════╩══════════════════════╩════════════╩══════════════╝
SET STATISTICS IO ON;
正しいクエリでこれを確認することもできます。8000バイトの行のみを調べる次のクエリを考えてみます。
SELECT SUM(LEN(MAX_VERNON_WAS_HERE))
FROM #LOB_FOR_ME
WHERE ID = 1;
実行時の結果:
スキャンカウント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;
今、私はロブの読み取りを見る:
スキャンカウント1、論理読み取り20、物理読み取り0、先読み読み取り0、LOB論理読み取り5080、LOB物理読み取り0、LOB先読み読み取り0。