Bir dizinde bir VARCHAR (MAX) sütunu varsa, değerin tamamı her zaman dizin sayfalarında depolanıyor mu?


12

Bunu meraktan, bu sorudan ilham alarak soruyorum .

Biz biliyoruz o VARCHAR(MAX)8000 bayt satır saklanmaz daha değerleri daha uzun fakat ayrı LOB sayfalarında. Daha sonra böyle bir değere sahip bir satırın alınması iki veya daha fazla mantıksal IO işlemi gerektirir (temel olarak, teorik olarak başka bir şeyden fazlası gerekir).

Bağlantılı soruda gösterildiği gibi, benzersiz bir dizine d VARCHAR(MAX)olarak bir sütun ekleyebiliriz INCLUDE. Bu sütun 8000 baytı aşan değerlere sahipse, bu değerler yine de dizin yaprağı sayfalarında "satır içi" olarak saklanır mı yoksa LOB sayfalarına da taşınır mı?

Yanıtlar:


16

8000 baytı aşan değerler "satır içi" olarak kaydedilemez. LOB sayfalarında saklanırlar. Bunu sys.dm_db_index_physical_stats ile görebilirsiniz . Basit bir tabloyla başlayın:

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);

Şimdi VARCHAR(MAX)sütun için 8000 bayt alan değerlere sahip bazı satırlar ekleyin ve DMF'yi kontrol edin:

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'); 

Dizinde LOB sayfası yok:

╔═════════════╦════════════════════╦══════════════════════╦════════════╦══════════════╗
 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 
╚═════════════╩════════════════════╩══════════════════════╩════════════╩══════════════╝

Ancak 8001 bayt alan değerlere sahip satırlar eklersem:

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'); 

Şimdi yeni eklediğim her satır için dizinde 1 LOB sayfası var:

╔═════════════╦════════════════════╦══════════════════════╦════════════╦══════════════╗
 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 
╚═════════════╩════════════════════╩══════════════════════╩════════════╩══════════════╝

Bunu SET STATISTICS IO ON;ve doğru sorgu ile de görebilirsiniz . Yalnızca 8000 baytlık satırlara bakan aşağıdaki sorguyu düşünün:

SELECT SUM(LEN(MAX_VERNON_WAS_HERE))
FROM #LOB_FOR_ME
WHERE ID = 1;

Yürütüldükten sonraki sonuçlar:

Tarama sayısı 1, mantıksal okuma 2560, fiziksel okuma 0, okuma öncesi okuma 0, lob mantıksal okuma 0, lob fiziksel okuma 0, lob okuma önceden okuma 0.

Bunun yerine 8001 bayt satırları sorgulamak:

SELECT SUM(LEN(MAX_VERNON_WAS_HERE))
FROM #LOB_FOR_ME
WHERE ID = 2;

Şimdi lobinin okuduğunu görüyorum:

Tarama sayısı 1, mantıksal okuma 20, fiziksel okuma 0, okuma öncesinde 0 okuma, lob mantıksal okuma 5080, lob fiziksel okuma 0, lob okuma öncesinde okuma 0.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.