2010-09-29 17 views
6

Mam złożony widok, którego używam do wyciągnięcia listy kluczy podstawowych wskazujących wiersze w tabeli, które zostały zmodyfikowane między dwoma punktami czasowymi.Łączenie z widokami w SQLServer z dziwnym zachowaniem optymalizatora zapytań

Ten widok musi sprawdzić 13 powiązanych tabel i przejrzeć tabelę dzienników zmian, aby określić, czy obiekt jest "brudny", czy nie.

Mimo wszystko to dzieje, wykonując proste zapytanie:

select * from vwDirtyEntities; 

zajmuje tylko 2 sekundy.

Jednak jeśli zmienię go

select 
    e.Name 
from 
    Entities e 
     inner join vwDirtyEntities de 
      on e.Entity_ID = de.Entity_ID 

ten trwa 1,5 minuty.

Jednakże, jeśli mogę to zrobić:

declare @dirtyEntities table 
(
    Entity_id uniqueidentifier; 
) 

insert into @dirtyEntities 
    select * from vwDirtyEntities; 


select 
    e.Name 
from 
    Entities e 
     inner join @dirtyEntities de 
      on e.Entity_ID = de.Entity_ID 

uzyskać takie same wyniki w ciągu zaledwie 2 sekund.

To prowadzi mnie do przekonania, że ​​SQLServer ocenia widok w wierszu po połączeniu z jednostkami, zamiast tworzyć plan kwerend, który obejmuje dołączenie pojedynczego wewnętrznego łączenia powyżej do innych sprzężeń w widoku.

Pamiętaj, że chcę dołączyć do pełnego zestawu wyników z tego widoku, ponieważ odfiltrowuje on tylko te klucze, które chcę wewnętrznie.

Wiem, że mógłbym zrobić to w zmaterializowanym widoku, ale wymagałoby to schematu wiążącego widok i jego zależności i nie podoba mi się obciążenie związane z utrzymaniem indeksu (Ten widok jest tylko wywoływany dla eksportu, podczas gdy o wiele więcej pisze do tabel podstawowych).

A więc, oprócz użycia zmiennej tabeli do buforowania wyników widoku, czy istnieje sposób, aby nakazać serwerowi SQL buforowanie widoku podczas oceniania łączenia? Próbowałem zmienić kolejność łączenia (wybierz z widoku i połącz z jednostkami), ale to nie miało znaczenia.

Sam widok jest bardzo wydajny i nie ma tu miejsca na optymalizację.

Odpowiedz

5

W widoku nie ma nic magicznego. To makro, które się rozszerza. Optymalizator decyduje, kiedy JOINed rozszerzy widok na główne zapytanie.

będę reagować na inne punkty w swoim poście:

  • zostały wykluczone indeksowany widok. Widok może być tylko dyskretną jednostką, gdy jest indeksowany. SQL Server nigdy nie wykona kwerendy RBAR na własną. Tylko programiści mogą pisać pętle.

  • nie istnieje pojęcie buforowania: każde zapytanie wykorzystuje najnowsze dane, jeśli nie używać tabel tymczasowych

  • upierasz się przy użyciu widoku, który zdecydowałeś jest bardzo wydajny.Ale nie mam pojęcia, jak poglądy są traktowane przez optymalizator i ma tabele

  • SQL jest deklaratywny: DOŁĄCZ porządek zazwyczaj nie ma znaczenia

  • wielu poważnych DB deweloper nie używaj widoki z powodu ograniczeń w ten sposób: nie można ich użyć ponownie, ponieważ są to makra:

Edytuj, inna możliwość. Predicate pushing na SQL Server 2005. Oznacza to, że SQL Server nie może przekazać warunku JOIN "głębiej" do widoku.

+0

Jeśli spojrzysz na historię edycji postów dla kucyków Omg, zobaczysz, że odpowiedziałem prostym komentarzem (nadal tam), a on odszedł od rzeczywistości. W kontekście, oto jego oryginalna odpowiedź: http://stackoverflow.com/revisions/2be5678d-7d09-4c14-9043-c4769f9f9c03/view-source. – FlySwat

+0

Tutaj jest edycja, którą zrobił po moim komentarzu: http://stackoverflow.com/revisions/0d5a1cb1-1f89-4fba-96f4-c270d0543805/view-source. Nigdy go nie atakowałem, zaczął wyrzucać. – FlySwat

+0

W odniesieniu do kolejności dołączania nie ma znaczenia. To może być prawdą w teorii, ale w praktyce widziałem, że jawne porządkowanie połączeń jest korzystne, zazwyczaj dlatego, że pozwala bazy danych na odrzucanie większych zestawów danych, które nie będą pasować przed oceną innych sprzężeń. – FlySwat

Powiązane problemy