2012-04-06 12 views
21

Używam MSSQL Server 2008 R2 i próbuję zoptymalizować moje widoki, gdy natknąłem się na widoki indeksowane. Niestety większość moich widoków używa lewych zewnętrznych połączeń, które nie są obsługiwane w widokach indeksowanych. Po serii badań, nie mam pojęcia, jak najlepiej to osiągnąć. Tak jak ja to widzę, mam następujące opcje:Zindeksowane widoki i lewe połączenia raz na zawsze

1) przekonwertować lewej dołącza do sprzężenia wewnętrzne stosując podstęp, aby symulować LEFT JOIN z "OR (IsNull (a) i IsNull (b))"

Znalazłem to rozwiązanie w kilku miejscach, ale wspomniałem o utracie wydajności.

2) Konwersja lewej łączy się z wewnętrzną łączy się i zastępuje null w pustych kolumny z pustymi GUID (00000000-0000-0000-0000-000000000000) i dodać jeden wiersz w odpowiedniej tablicy z pasującym GUID.

Wydaje się to najbardziej oczywiste pod względem wydajności, ale wydaje się marnowaniem miejsca na każdy wiersz, który w przeciwnym razie byłby NULL.

3) Podziel mój widok na dwa widoki. Pierwszy widok to większość mojej logiki, która jest indeksowalna. Drugi widok wynika z pierwszego widoku i dodanie lewych złączeń.

Pomysł polega na tym, że może nastąpić wzrost wydajności poprzez indeksowanie widoku podstawowego. I nawet zapytanie o widok pochodny przyniosłoby przynajmniej część korzyści z wydajności.

4) NIE indeks moje poglądy

byłoby pozostawienie na stanowisku, tak jest bardziej wydajnych niż którykolwiek z powyższych opcji?

5) Pomysł nie myśleć

I skryptów mój podstawowy scenariusz następująco:

CREATE TABLE [dbo].[tbl_Thumbnails](
     [ThumbnailId] [uniqueidentifier] NOT NULL, 
     [Data] [image] NULL, 
     [Width] [smallint] NOT NULL, 
     [Height] [smallint] NOT NULL 
    CONSTRAINT [PK_tbl_Thumbnails] PRIMARY KEY CLUSTERED 
    (
     [ThumbnailId] ASC 
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 

    GO 

    CREATE TABLE [dbo].[tbl_Tags](
     [TagId] [uniqueidentifier] NOT NULL, 
     [ThumbnailId] [uniqueidentifier] NULL 
    CONSTRAINT [PK_tbl_Tags] PRIMARY KEY CLUSTERED 
    (
     [TagId] ASC 
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
    ) ON [PRIMARY] 

    GO 

    CREATE VIEW [dbo].[v_Tags] WITH SCHEMABINDING AS 
    SELECT  dbo.tbl_Tags.TagId, dbo.tbl_Tags.ThumbnailId 
    FROM   dbo.tbl_Tags LEFT OUTER JOIN 
          dbo.tbl_Thumbnails 
    ON  dbo.tbl_Tags.ThumbnailId = dbo.tbl_Thumbnails.ThumbnailId 

    GO 

    INSERT INTO tbl_Tags VALUES ('16b23bb8-bf17-4784-b80a-220da1163584', NULL) 
    INSERT INTO tbl_Tags VALUES ('e8b50f03-65a9-4d1e-b3b4-268f01645c4e', 'a45e357b-ca9c-449a-aa27-834614eb3f6e') 
    INSERT INTO tbl_Thumbnails VALUES ('a45e357b-ca9c-449a-aa27-834614eb3f6e', NULL, 150, 150) 

Teraz robi następujące wydajności zapytań „Nie można utworzyć indeks na widoku” Test .dbo.v_Tags. „ponieważ używa lewej, prawej lub FULL OUTER JOIN, a brak sprzężenia zewnętrzne są dozwolone w widoków indeksowanych rozważyć użycie zamiast sprzężenia wewnętrznego.”:

CREATE UNIQUE CLUSTERED INDEX [TagId] ON [dbo].[v_Tags] 
(
[TagId] ASC 
) 
GO 

To jest oczekiwane zachowanie, ale jaki sposób działania zaleciłbyś uzyskać najlepszą wydajność z mojego scenariusza? Punktem wyjścia do domu jest najlepsza wydajność.

+1

Czego kończy się robi z tym? Mam do czynienia z podobnym problemem, próbując zindeksować niektóre opinie. – user1948635

+0

W podobnej sytuacji, tabela denormalizowana (z wyzwalaczami lub inny sposób jej aktualizacji) może być również opcją na liście. –

+0

Odpowiedziałem na bardzo podobne pytanie dotyczące materializowania indeksów dla lewych złączeń. Chociaż nie ma bezpośredniego sposobu, aby to zrobić ... tutaj jest opcja # 5 http://stackoverflow.com/a/31171129/1902664 – cocogorilla

Odpowiedz

6

Dlaczego indeksujesz swoje poglądy? Wspomniałeś o "marnowaniu przestrzeni" w rozwiązaniu 2, ale czy wiesz, że kiedy indeksujesz swój widok, utrzymujesz go w DB?

Innymi słowy, tworzysz kopię danych, które widok zwróci w DB i za każdym razem, gdy dane zostaną zaktualizowane w tabelach źródłowych, niektóre wewnętrzne mechanizmy SQL Servera muszą zaktualizować je na tej nowej utworzonej strukturze danych ponieważ teraz serwer SQL czyta z widoku, a nie z tabel.

Jeśli używasz Profiler + DTA lub nawet DMVS można wymyślić z odpowiednimi indeksami zostać utworzony na tabelach, że każdy pogląd skorzystałyby

+1

Co jeśli widok przedstawia prawie stałe dane (rzadko zmieniane w tabelach) i jest również używane w wielu miejscach? Widok indeksowany bardzo pomaga w osiągnięciu wydajności w tym przypadku – Thetam

+0

w takim przypadku, tak. Masz rację: – Diego

+2

Musisz również zindeksować swój widok, jeśli chcesz utworzyć na nim indeks pełnotekstowy. –

Powiązane problemy