Nieklastrowane przechowywanie indeksu w klastrowanym magazynie kolumn

18

W SQL Server nieunikalny indeks nieklastrowany w tabeli magazynu wierszy zawiera zakładkę obiektu podstawowego (RID lub klucz klastrowania) na wszystkich poziomach struktury indeksu nieklastrowanego. Zakładka jest przechowywana jako część nieklastrowanego klucza indeksu na wszystkich poziomach indeksu.

Z drugiej strony, jeśli indeks nieklastrowany jest unikalny , zakładka jest obecna tylko na poziomie liścia indeksu - nie jako część klucza (zakładka jest obecna jako jedna lub więcej uwzględnionych kolumn).

W SQL Server 2016 możliwe jest zbudowanie nieklastrowanego indeksu b-drzewa na tabeli zorientowanej na kolumny (takiej, która ma klastrowany indeks magazynu kolumn).

  1. Jaka „zakładka” jest używana dla nieklastrowego indeksu b-drzewa w klastrowanej tabeli magazynu kolumn?
  2. Czy różnice między unikatowymi i nieunikalnymi indeksami nieklastrowymi opisane powyżej nadal obowiązują?
Paul White 9
źródło

Odpowiedzi:

17
  1. „Zakładka” to oryginalny lokalizator indeksu magazynu kolumn (według „Pro SQL Server Internals” Dmitrija Korotkevitcha). Jest to wartość 8-bajtowa, z indeksem magazynu kolumn row_group_idw pierwszych 4 bajtach i przesunięciem w drugich 4 bajtach.

  2. Jeśli użyjesz, DBCC PAGEaby spojrzeć na indeks nieklastrowany, 8-bajtowy oryginalny lokalizator indeksu magazynu kolumn pojawi się w kolumnie „unikalizatora” DBCC PAGEwyniku. Pokazuje to, że unikalny nieklastrowanym indeks nie muszą zawierać lokalizator columnstore rzędu, podczas gdy nie-unikalny wskaźnik nieklastrowanym nie.

Poniższy kod tworzy tabelę zorganizowaną w magazynie kolumn z unikalnym i nieunikalnym nieklastrowanym indeksem b-drzewa w tej samej kolumnie:

CREATE TABLE dbo.Heapish
(
    c1 bigint NOT NULL,
    c2 bigint NOT NULL,
    INDEX CCI_dbo_Heapish CLUSTERED COLUMNSTORE
);
GO
INSERT dbo.Heapish WITH (TABLOCKX)
    (c1, c2)
SELECT TOP (1024 * 1024 * 8)
    c1 = ROW_NUMBER() OVER
        (ORDER BY C1.[object_id], C1.column_id),
    c2 = ROW_NUMBER() OVER
        (ORDER BY C1.[object_id], C1.column_id)
FROM master.sys.columns AS C1
CROSS JOIN master.sys.columns AS C2
ORDER BY
    c1
OPTION (MAXDOP 1);
GO
CREATE UNIQUE NONCLUSTERED INDEX UNIQUE_c2 ON dbo.Heapish (c2) WITH (MAXDOP = 1);
CREATE NONCLUSTERED INDEX NONUNIQUE_c2 ON dbo.Heapish (c2) WITH (MAXDOP = 1);

Możemy zobaczyć rozmiar wiersza indeksu na różnych poziomach b-drzewa, używając sys.dm_db_index_physical_stats:

SELECT
    DDIPS.index_level,
    DDIPS.page_count,
    DDIPS.record_count,
    DDIPS.min_record_size_in_bytes,
    DDIPS.max_record_size_in_bytes
FROM sys.dm_db_index_physical_stats
(
    DB_ID(),
    OBJECT_ID(N'dbo.Heapish', N'U'),
    INDEXPROPERTY(OBJECT_ID(N'dbo.Heapish', N'U'), N'UNIQUE_c2', 'IndexID'),
    NULL, 'DETAILED'
) AS DDIPS;

SELECT
    DDIPS.index_level,
    DDIPS.page_count,
    DDIPS.record_count,
    DDIPS.min_record_size_in_bytes,
    DDIPS.max_record_size_in_bytes
FROM sys.dm_db_index_physical_stats
(
    DB_ID(),
    OBJECT_ID(N'dbo.Heapish', N'U'),
    INDEXPROPERTY(OBJECT_ID(N'dbo.Heapish', N'U'), N'NONUNIQUE_c2', 'IndexID'),
    NULL, 'DETAILED'
) AS DDIPS;

Dane wyjściowe to:

Unikalny indeks

Indeks nonunqiue

Obie struktury mają taki sam rozmiar wiersza na poziomie liścia, ale nietypowy indeks nieklastrowany jest o 12 bajtów większy niż unikalny indeks nieklastrowany na poziomach nie-liścia dzięki 8-bajtowemu lokalizatorowi magazynu kolumn plus 4 bajty narzutu dla pierwszej zmiennej -długość kolumny z rzędu (uniquifier ma zmienną długość).

AMtwo
źródło
A jeśli odpowiedni wiersz znajduje się w sklepie delta? Co się stanie, gdy sklep Delta będzie kompresowany?
Artash Khachatryan