Nilai yang melebihi 8000 byte tidak dapat disimpan "inline". Mereka disimpan di halaman LOB. Anda dapat melihat ini dengan sys.dm_db_index_physical_stats . Mulai dengan tabel sederhana:
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);
Sekarang masukkan beberapa baris dengan nilai yang mengambil 8000 byte untuk VARCHAR(MAX)
kolom dan periksa 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');
Tidak ada halaman LOB dalam indeks:
╔═════════════╦════════════════════╦══════════════════════╦════════════╦══════════════╗
║ 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 ║
╚═════════════╩════════════════════╩══════════════════════╩════════════╩══════════════╝
Tetapi jika saya menambahkan baris dengan nilai yang mengambil 8001 byte:
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');
Sekarang saya memiliki 1 halaman LOB dalam indeks untuk setiap baris yang baru saja saya masukkan:
╔═════════════╦════════════════════╦══════════════════════╦════════════╦══════════════╗
║ 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 ║
╚═════════════╩════════════════════╩══════════════════════╩════════════╩══════════════╝
Anda juga dapat melihat ini dengan SET STATISTICS IO ON;
dan permintaan yang tepat. Pertimbangkan kueri berikut yang hanya melihat baris dengan 8000 byte:
SELECT SUM(LEN(MAX_VERNON_WAS_HERE))
FROM #LOB_FOR_ME
WHERE ID = 1;
Hasil setelah dieksekusi:
Pindai hitungan 1, pembacaan logis 2560, pembacaan fisik 0, pembacaan read-ahead 0, pembacaan logis lob 0, pembacaan fisik lob 0, pembacaan lob baca-depan 0.
Jika saya sebagai gantinya meminta baris dengan 8001 byte:
SELECT SUM(LEN(MAX_VERNON_WAS_HERE))
FROM #LOB_FOR_ME
WHERE ID = 2;
Sekarang saya melihat lob berbunyi:
Pindai hitungan 1, bacaan logis 20, bacaan fisik 0, bacaan baca-depan 0, bacaan lob logis 5080, bacaan fisik lob 0, bacaan lob baca-depan 0.