2012-08-11 7 views
5

Mam kilka identyfikatorów wstawiane do tabeli temp #A następująco:Dwa zapytania. Ten sam wynik. Jeden zajmuje 2 godziny, a drugi 0 sekund. Czemu?

SELECT DISTINCT ID 
INTO #A 
FROM LocalDB.dbo.LocalTable1 
WHERE ID NOT IN (SELECT DISTINCT ID FROM LocalDB.dbo.LocalTable2) 
GO 

CREATE INDEX TT ON #A(ID) 
GO 

Próbuję uzyskać pewne informacje ze zdalnego serwera połączonego za pomocą identyfikatorów Zebrałem w poprzednim etapie:

Query 1:

SELECT ID, Desc 
FROM RemoteLinkedServer.DB.dbo.RemoteTable X 
WHERE ID IN (SELECT ID FROM #A) 

Zapytanie 2:

SELECT ID, Desc 
FROM RemoteLinkedServer.DB.dbo.RemoteTable X 
INNER JOIN #A Y 
ON X.ID = Y.ID 

Teraz, w poniższym zapytaniu, robię to, uzyskując dane wyjściowe tabeli tymczasowej, skopiuj wiersze i sformatuj je poprawnie na listę oddzielaną przecinkami i ręcznie wstaw ją do zapytania.

Zapytanie 3:

SELECT ID, Desc 
FROM RemoteLinkedServer.DB.dbo.RemoteTable X 
WHERE ID IN (-- Put all identifiers here --) 

zapytania 1 i 2 się przez 2 godziny do wykonania i wykonuje zapytanie 3 0 s (my tabela zawiera temperatury około 200 wiersze). Nie wiem, co się dzieje i nie mam uprawnień do sprawdzenia, czy serwer zdalny ma odpowiednie indeksy na ID, ale jest po prostu kłopotliwy, gdy zobaczy, że ręcznie utworzone zapytanie uruchamia się w krótkim czasie, wskazując, że coś jest nie tak w fazie optymalizacji zapytania.

Jakieś pomysły na temat tego, co się tutaj nie zgadza lub jak mogę przyspieszyć moje zapytanie?

Odpowiedz

10

Kwerendy 1 i 2 powodują, że WSZYSTKIE dane w tabeli zdalnej zostaną wciągnięte do lokalnej bazy danych w celu wykonania operacji łączenia. To będzie jeść RAM, przepustowość sieci i generalnie będzie bardzo wolno podczas wykonywania kwerendy.

Zapytanie 3 pozwala serwerowi odfiltrować wyniki, aby wysłać tylko te dopasowania, które chcesz.

Zasadniczo sprowadza się to do tego, kto wykonuje pracę. Kwerendy 1/2 wymagają wykonania tego przez lokalną bazę danych; Zapytanie 3 pozwala zdalnemu zrobić to.

Jeśli masz dużo danych w tej tabeli zdalnej, a następnie będziesz prawdopodobnie napotkasz przeciążenia sieci itp

Najlepszym podejściem do odpytywania serwerów połączonych jest skonstruowanie zapytania takie jak zdalny serwer robi wszystko pracę i po prostu wysyła wyniki z powrotem do twojego lokalnego. Pozwoli to zoptymalizować ilość zasobów sieciowych, pamięci i dysków wymaganych do uzyskania żądanych danych.

Za każdym razem, gdy musisz połączyć się z granicami serwera (używając połączonego serwera), stanie się to katastrofą.

+1

+1 Szczerze mówiąc, nie wiem! Dziękuję za wyjaśnienie. Jak więc wysłać moje lokalne wartości do zdalnego serwera połączonego i otrzymać wyniki? 'CURSOR's, a następnie wysłać jeden identyfikator na raz? Zdalny stół jest ogromny z około 10 milionami wierszy. – Legend

+2

Prawdopodobnie najlepszym rozwiązaniem jest dynamiczne budowanie sql do wykonania na serwerze zdalnym i po prostu WYKONUJ.Odkryliśmy, że ta metoda jest o wiele szybsza w przypadku każdego rodzaju połączenia, które wykonujemy z połączonymi serwerami. Używanie kursora, a następnie uruchamianie jednego zapytania naraz może spowodować przekroczenie limitów prędkości transakcji; której możesz nie chcieć. – NotMe

+0

Dziękuję za sugestię. Nie ma więcej wąskich gardeł i mój skrypt działa dobrze z tą optymalizacją. – Legend

3

Dla porównania, to w jaki sposób rozwiązać ten problem na podstawie @ ChrisLively na sugestie:

SELECT DISTINCT ID 
INTO #A 
FROM LocalDB.dbo.LocalTable1 
WHERE ID NOT IN (SELECT DISTINCT ID FROM LocalDB.dbo.LocalTable2) 
GO 

CREATE INDEX TT ON #A(ID) 
GO 

DECLARE @IDList VARCHAR(MAX) 
SELECT @IDList=(SELECT TOP 1 REPLACE(RTRIM((
       SELECT DISTINCT CAST(ID AS VARCHAR(MAX)) + ' ' 
       FROM #A AS InnerTable    
       FOR XML PATH (''))),' ',', ')) 
FROM #A AS OuterResults 


DECLARE @sql AS varchar(MAX) 
SET @sql = 'SELECT * FROM RemoteLinkedServer.RemoteDB.dbo.RemoteTable X WHERE ID IN (' + @IDList + ')' 

EXEC (@sql) 

DROP TABLE #A 
GO 
+0

Dokładnie podchodzę do tego. – NotMe

+0

@ChrisLive: Dziękujemy za potwierdzenie :) – Legend

Powiązane problemy