Muszę wybrać wiersze z tabeli BUNDLES, które mają jedną z kilku wartości SAP_STATE_ID. Wartości te zależą od tego, czy dany status SAP ma zostać wyeksportowany, czy nie.Dlaczego podzapytanie i dołączanie są tak powolne?
Ta kwerenda działa bardzo szybko (istnieje indeks na polu SAP_STATE_ID) -
SELECT b.* FROM BUNDLES b WHERE b.SAP_STATE_ID IN (2,3,5,6)
Ale ... Chciałbym listę identyfikatorów pobierać dynamicznie, tak:
SELECT b.* FROM BUNDLES b
WHERE b.SAP_STATE_ID IN
(SELECT s.SAP_STATE_ID FROM SAP_STATES s WHERE s.EXPORT_TO_SAP = 1)
I ouch, to zapytanie nagle zajmuje zbyt dużo czasu. Spodziewam się, że najpierw serwer SQL uruchomi podzapytanie (nie zależy to od niczego z głównej kwerendy), a następnie uruchomi całą sprawę tak, jak w moim pierwszym przykładzie. Próbowałem przepisać go, aby użyć połączeń zamiast podzapytania:
SELECT b.* FROM BUNDLES b
JOIN SAP_STATES s ON (s.SAP_STATE_ID = b.SAP_STATE_ID)
WHERE s.EXPORT_TO_SAP = 1
, ale ma tę samą słabą wydajność. Wygląda na to, że uruchamia podzapytanie dla każdego wiersza tabeli BUNDLES lub coś podobnego. Nie mam umiejętności czytania planów wykonania, ale próbowałem. Mówi się, że 81% koszt jest przeznaczony na skanowanie Primary key index BUNDLES (nie mam pojęcia, dlaczego powinien to zrobić, jest pole BUNDLE_ID zdefiniowane jako PRIMARY KEY, ale w ogóle nie pojawia się w zapytaniu ...)
Czy ktoś ma wyjaśnienie, dlaczego serwer SQL jest tak "głupi"? Czy istnieje sposób na osiągnięcie tego, co chcę, przy dobrej wydajności, ale bez potrzeby podawania statycznej listy identyfikatorów SAP_STATE_ID?
scenariusz dla obu tabel i odpowiednich indeksów - Plan http://mab.to/xbYiI0wKj
wykonania dla wersji podzapytanie - http://mab.to/8Qh6gpdYZ
planu kwerend dla wersji ze sprzężeń - http://mab.to/YCqeGCUbr
(z jakiegoś powodu te dwa plany wygląda tak samo i oba sugerują utworzenie indeksu BUNDLES.SAP_STATE_ID, który już istnieje)
Czy masz indeksu na SAP_STATES.SAP_STATE_ID? –
tak, jest to klucz podstawowy faktycznie – lot
Jak długo trwa wykonywanie podkwerendy? – DavidG