Indeksowanie kolumny typu NVARCHAR(MAX)

Bardzo rzadko piszę tutaj, jest to spowodowane tym że jestem leniwym, ale dziś zwalczyłem leń i przekazuję do użytku publicznego prostą receptę na indeksowanie kolumny typu NVARCHAR(MAX).

Ostatnio zderzyłem się z wydajnością jednej z procedur składowanej (ang. stored procedure), a mianowicie – łączenie tabeli z inną tabelą po kolumnie tupy NVARCHAR(MAX) daje bardzo słabą wydajność prz >1k rekordów w tabeli. Teraz każdy może powiedzieć – no panie, wiadomo że trzeba założyć indeksy 😀

I macie racje, tylko że SQL Server nie pozwala tworzyć indeks na gdy rozmiar wszystkich kolumn w indeksie przekracza 900 bajtów (link). A więc zaczęłem myśleć i szukać rozwiązania.

Odrazu wpadłem na pomysł żeby przy wstawianiu rekordu do tabeli w wyzwalaczu konwertować dane tej kolumny do postaci liczby, żeby udało się założyć na tym indeks. Skorzystałem z funkcji CHECKSUM która umożliwia na kalkulacje sumy kontrolnej wiersza w tabeli, kolumny, itd. To rozwiązanie zadziałało i dało przyrost wydajności prawie 5 razy 🙂 Potem to jeszcze zrefaktoryzowałem – wyrzuciłem wyzwalacz i przekształciłem dodatkową kolumnę na kolumnę obliczeniową.

Trochę kodu:

CREATE TABLE [dbo].[Clients]
(
    [Number] BIGINT NULL, 
    [FirstName] NVARCHAR(MAX) NULL, 
    [LastName] NVARCHAR(MAX) NULL, 
    [Email] NVARCHAR(MAX) NULL, 
    [EmailChecksum] AS 
		CASE WHEN Email IS NULL
			THEN NULL
			ELSE CHECKSUM(Email)
		END
)

GO

CREATE NONCLUSTERED INDEX [IX_Clients_Number] ON [dbo].[Clients] ([Number]) INCLUDE ([EmailChecksum])

GO