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