Mam zapytanie, które trwa 2,5 sekundy przy użyciu opcji FULL JOIN i 40 sekund przy użyciu INNER, RIGHT lub LEFT JOIN.W jaki sposób INNER/RIGHT/LEFT JOIN mogą być 14 razy wolniejsze niż FULL JOIN?
Oto zapytanie. Podzapytowanie (wykonane dwukrotnie) zajmuje tylko 1,3 sekundy.
SELECT T1.[time], T1.Total, T1.rn, T2.[time], T2.Total, T2.rn
FROM
(
select [time], MAX(ComputedValue) as Total, row_number() over (order by [time]) as rn
FROM
(
select SUBSTRING(CONVERT(CHAR(10), IntervalStartTime, 108), 0, 6) as [time], ComputedValue
from LoadTestTransactionSample
where LoadTestRunId=285
and CounterName='Total Transactions'
and TransactionName='Export'
) foo
group by [time]
) T1
_____ JOIN
(
select [time], MAX(ComputedValue) as Total, row_number() over (order by [time]) as rn
FROM
(
select SUBSTRING(CONVERT(CHAR(10), IntervalStartTime, 108), 0, 6) as [time], ComputedValue
from LoadTestTransactionSample
where LoadTestRunId=285
and CounterName='Total Transactions'
and TransactionName='Export'
) foo
group by [time]
) T2
ON T1.rn = T2.rn - 1
select SUBSTRING
bit jest po prostu coraz HH: MM ciąg z DateTime. LoadTestTransactionSample
to właściwie WIDOK, który łączy się z 8 stołami. (FYI baza danych to magazyn wyników testu obciążenia programu Visual Studio). Oto jego (istotne) kolumny:
LoadTestRunId INT NOT NULL
CounterName NVARCHAR(255) NOT NULL
TransactionName NVARCHAR(64) NOT NULL
IntervalStartTime DATETIME NOT NULL
IntervalEndTime DATETIME NOT NULL
ComputedValue REAL
pełnego złączenia powraca dodatkowy niepotrzebny wiersz, więc trzeba zrobić RIGHT JOIN, aby uzyskać właściwą odpowiedź.
nie jestem naprawdę szuka rozwiązania (mam jedną:
pre-fetch podzapytania w tabeli zmiennej
używać SQL Server 2012 analityczną funkcję "LGD, dzięki @ a1ex07), po prostu pewne zrozumienie jako do , co może spowodować ekstremalną różnicę w wydajności między tymi typami łączenia.
EDIT: Oto slow right join query plan i fast full join query plan. Są za duże, by opublikować zrzut ekranu.
EDIT 2: Właściwie plany zapytań mają prawo JOIN na poziomie 45% i pełnego złączenia w 55%, co okazuje się być kompletnie nieprawdziwe (w rzeczywistości kończy się gorzej niż 99%/1%). Sądzę, że oznacza to, że muszę polegać na faktycznych statystykach wykonania.
EDIT 3: Statystyki dla powolnego RIGHT JOIN:
(40 row(s) affected)
Table 'LoadTestPerformanceCounterCategory'. Scan count 0, logical reads 37556, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'LoadTestPerformanceCounter'. Scan count 0, logical reads 176464, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'LoadTestScenario'. Scan count 0, logical reads 176464, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'LoadTestCase'. Scan count 0, logical reads 176464, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'WebLoadTestTransaction'. Scan count 0, logical reads 13411100, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'LoadTestPerformanceCounterInstance'. Scan count 0, logical reads 36563718, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'LoadTestPerformanceCounterSample'. Scan count 19721, logical reads 269657, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'LoadTestRunInterval'. Scan count 41, logical reads 205, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 36754 ms, elapsed time = 36763 ms.
Statystyki dla szybkiego pełnego złączenia:
(41 row(s) affected)
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'LoadTestPerformanceCounterCategory'. Scan count 0, logical reads 1832, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'LoadTestPerformanceCounter'. Scan count 0, logical reads 8608, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'LoadTestScenario'. Scan count 0, logical reads 8608, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'LoadTestCase'. Scan count 0, logical reads 8608, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'WebLoadTestTransaction'. Scan count 0, logical reads 654200, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'LoadTestPerformanceCounterInstance'. Scan count 0, logical reads 1783596, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'LoadTestPerformanceCounterSample'. Scan count 962, logical reads 13154, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'LoadTestRunInterval'. Scan count 2, logical reads 10, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 1950 ms, elapsed time = 1944 ms.
prawo JOIN robi znacznie więcej odsłon i więcej skanów niż FULL JOIN, mimo podobno podobnego planu zapytania.
Czy Stół roboczy (w PEŁNYM DOŁĄCZU) podpowiedź? Czy to stolik tymczasowy?
Czy to sugeruje, że optymalizator zapytań jest zepsuty?
Ustaw statystyki planu zapytania/wyświetlacz dalej i widzieć. Bez skryptów DDL, aby móc replikować swój schemat i dane, każda odpowiedź jest w zasadzie zgadywana. Czy te wartości wydajności różnią się w pierwszym zapytaniu, podobnie jak w przypadku kolejnych zapytań? To oznacza, że angażujesz się w pamięć podręczną. – Heather
Myślę, że Heather chce poprosić o ich wykonanie 1-2-3-4, a następnie 4-3-2-1 i porównać –
Ponadto, każda wersja zapytania generuje własny plan zapytania w pamięci podręcznej, a te nie są koniecznie odświeżony w tym samym czasie. Może to prowadzić do sporadycznych problemów z wydajnością. –