2012-01-25 15 views
5

Natknąłem się na tę bardzo dziwną sytuację i pomyślałem, że podrzucę ją tłumowi, aby dowiedzieć się dlaczego.WEJŚCIE WEWNĘTRZNE na podłączonym serwerze Tabela znacznie wolniejsza niż pod-zapytania

Mam zapytanie, które zostało łączący tabelę na połączonym serwerze:

select a.*, b.phone 
from table_a a, 
join remote.table_b b on b.id = a.id 
(lots of data on A, but very few on B) 

ta kwerenda mówił zawsze (nigdy nie dowiedziałem się rzeczywisty czas pracy), a to jest, gdy zauważyłem B nie miał indeks, więc dodałem go, ale to nie rozwiązało problemu. Wreszcie, z rozpaczy próbowałem:

select a.*, b.phone 
from table_a a, 
join (select id, phone from remote.B) as b on b.id = a.id 

Ta wersja zapytaniu, w moim umyśle jak najmniej, powinny mieć takie same wyniki, ale lo i oto jej odpowiadać natychmiast!

Jakieś pomysły, dlaczego ktoś zawiesiłby się, a drugi proces szybko? I tak, zaczekałem, aby upewnić się, że indeks został zbudowany przed uruchomieniem obu.

+0

Czy spojrzałeś na plan wykonania dla obu? Czy różnią się? Czy wydałeś _dbcc dropcleanbuffers_ pomiędzy każdą metodą? – canon

+0

Mniej więcej ile rekordów znajduje się w 'remote.B'? – Yuck

+0

"Zdalny" DB znajduje się na innym serwerze, do którego można uzyskać dostęp za pośrednictwem serwera linkserver i istnieje około 600 wierszy. – Limey

Odpowiedz

4

To dlatego, że czasami (bardzo często) realizacja planów automatycznie generowanego przez Silnik serwera sql nie są tak dobre i oczywiste, jak chcemy. Możesz spojrzeć na plan wykonania w obu sytuacjach. Sugeruję użycie wskazówki w pierwszym zapytaniu, coś takiego: INNER MERGE JOIN.

Oto więcej informacji na ten temat:

http://msdn.microsoft.com/en-us/library/ms181714.aspx

+0

To miła nowa rzecz, której nauczyłem się dzisiaj! Znam inne miejsca, w których mogę korzystać z tego rodzaju połączenia. – Limey

+0

Używam podpowiedzi scalania, aby połączyć widok (utworzony z 3 tabel) i tabelę. Widok już ma plan wykonania, ale nawet ten silnik tworzy nowy, o wiele wolniejszy. To jest kolejny przypadek, kiedy możesz go znaleźć. – devarc

+3

'MERGE' nie jest magiczną wskazówką" idź szybciej ". Jeśli nie otrzymujesz odpowiedniego planu, lepiej najpierw zrozumieć dlaczego. –

1

Zdalny stół jak na tym serwerze? Czy jest możliwe, że sprzężenie rzeczywiście wywołuje wiele wywołań do tabeli zdalnej, podczas gdy podzapytanie wykonuje jedno żądanie dla kopii danych tabeli, co skutkuje mniejszą ilością czasu oczekiwania w sieci?

+0

'~ 600' w tabeli zdalnej. Znajdź coś, co będzie wspierać ideę, że podzapytanie powoduje, że cała tabela jest buforowana, a to dostaje mój +1 – Yuck

+0

Szacowany plan wykonania pokazuje, że tylko uzyskuje dostęp do niego raz w obu wersjach zapytania. Zły szacuje się na 40% przetwarzania, a drugi na 1% – Limey

+0

Limey, jakie jest dokładne sformułowanie w planie wykonania? Byłbym zaskoczony, gdyby rzeczywiście wskazywał liczbę wywołań wykonanych wewnętrznie dla tego procesu. –

3

Dla serwerów połączonych 2-ty wariant wstępnie wyłapuje wszystkie dane lokalnie, a nie łączenia, od dnia 1 wariant może zrobić inner loop join podroż dookoła do połączonego serwera dla każdego wiersza w

+0

@Limey dla pierwszego wariantu obejrzenia ** Liczba wykonań ** w zapytaniu o plan połączenia zdalnego - jeśli jest więcej niż 1, to ** robi ** roundtripd dla danych –

+0

Sprawdzono szacunkowy plan wykonania; nie łączy się z nią wewnętrzna pętla dla tego stołu. – Limey

+1

@Liney - Jaka jest ** liczba egzekucji ** dla zdalnego elementu tabeli? Lub pokaż nam cały plan zapytania jako XML –

1

jestem po prostu będzie musiał zgadywać tutaj. Kiedy uzyskujesz dostęp do remote.b to jest to tabela na innym serwerze?

Jeśli tak jest, powodem, dla którego druga kwerenda jest szybsza, jest to, że wykonujesz jedno zapytanie do drugiego serwera i dostajesz wszystkie potrzebne dane z b, przed przetworzeniem danych. W pierwszym zapytaniu przetwarzasz dane i jednocześnie wysyłasz kilka żądań do drugiego serwera.

Mam nadzieję, że ci to pomoże.