2009-12-08 10 views
82

Powiel możliwe:
T-SQL WHERE col IN (…)Maksymalny rozmiar zapytania SQL Server? Klauzula IN? Czy istnieje lepsze podejście

Jaki jest maksymalny rozmiar dla kwerendy SQL Server? (Liczba znaków)

Maksymalny rozmiar dla klauzuli IN? Wydaje mi się, że widziałem coś o Oracle, która ma limit 1000 przedmiotów, ale możesz obejść to razem z ANDing 2 INs razem. Podobny problem w SQL Server?

UPDATE Więc co byłoby najlepsze podejście, jeśli muszę wziąć powiedzieć 1000 GUID z innego systemu (dla relacyjnej bazy danych) i zrobić „przyłączyć się kodem” przeciwko SQL Server? Czy do przedstawienia wykazu 1000 GUID klauzuli IN? czy jest tam inna technika, która działa bardziej efektywnie?

nie testowałem tego, ale zastanawiam się, czy mogę złożyć GUID jako dokumentu XML. na przykład

<guids> 
    <guid>809674df-1c22-46eb-bf9a-33dc78beb44a</guid> 
    <guid>257f537f-9c6b-4f14-a90c-ee613b4287f3</guid> 
</guids> 

, a następnie wykonaj pewien rodzaj XQuery JOIN przeciwko Doc i tabela. Mniej sprawny niż 1000 pkt.

+1

Wydaje się być duplikatem: http: // stackoverflow. com/questions/1069415/t-sql-where-col-in – Yishai

+0

Pozwól mi dodać pytanie, aby było bardziej unikalne. zobacz aktualizację – BuddyJoe

+1

Zasób Znalazłem omawianie niektórych pomysłów - http://www.sommarskog.se/arrays-in-sql-2005.html#InsertMany – BuddyJoe

Odpowiedz

64

Każda partia SQL musi pasować do Batch Size Limit: 65 536 * Rozmiar pakietu sieciowego.

Poza tym zapytanie jest ograniczone warunkami runtime. Zwykle zabraknie rozmiaru stosu, ponieważ x IN (a, b, c) to nic innego jak x = OR x = b OR x = c, który tworzy drzewo wyrażeń podobne do x = a OR (x = b OR (x = c)), więc robi się bardzo głęboko z dużą liczbą OR. SQL 7 uderzyłby w SO at about 10k values in the IN, ale obecnie stosy są dużo głębsze (z powodu x64), więc może być dość głęboko.

Aktualizacja

można już znaleźć artykuł Erland na ten temat przechodzenia lists/tablic do SQL Server. Z SQL 2008 masz również Table Valued Parameters, który pozwala ci przekazać całą DataTable jako parametr o jednym typie tabeli i dołączyć do niego.

XML i XPath jest kolejnym rozwiązaniem:

SELECT ... 
FROM Table 
JOIN (
    SELECT x.value(N'.',N'uniqueidentifier') as guid 
    FROM @values.nodes(N'/guids/guid') t(x)) as guids 
ON Table.guid = guids.guid; 
+0

"rozmiar stosu": to błąd, którego nie pamiętam. – gbn

12

na partię, która jest 65536 * Network Packet Size 4k więc 256 MB

Jednak w zatrzyma drogę wcześniej, ale to nie jest precyzyjne.

W rezultacie pojawiają się błędy pamięci, ale nie pamiętam dokładnego błędu. Ogromne IN będzie i tak nieefektywne.

Edit: Remus przypomniał mi: błąd jest o "wielkości stosu"

34

SQL Server Górne limity są ujawnione http://msdn.microsoft.com/en-us/library/ms143432.aspx (jest to wersja 2008) kwerend

SQL może być varchar (max) ale jest pokazany jako ograniczony do 65 536 * rozmiaru pakietu sieciowego, ale nawet wtedy najbardziej prawdopodobne, że cię potknie, jest 2100 parametrów na zapytanie. Jeśli SQL zdecyduje się sparametryzować literalne wartości w klauzuli "w", myślę, że najpierw byś trafił w ten limit, ale ja go nie przetestowałem.

Edycja: Przetestuj, nawet w przypadku wymuszonej parametryzacji przetrwał - Szybko przetasowałem i kazałem go wykonywać z 30k pozycji w klauzuli "In". (SQL Server 2005)

Na 100k przedmioty, zajęło trochę czasu, następnie spadł z:

Msg 8623, Level 16, State 1, wiersz 1 Procesor kwerend zabrakło zasobów wewnętrznych i nie mógł wytworzyć plan zapytania. Jest to rzadkie zdarzenie i jest oczekiwane tylko w przypadku bardzo złożonych zapytań lub zapytań, które odnoszą się do bardzo dużej liczby tabel lub partycji. Uprośnij zapytanie. Jeśli uważasz, że otrzymałeś tę wiadomość przez pomyłkę, skontaktuj się z Obsługą klienta, aby uzyskać więcej informacji.

30k więc jest możliwe, ale tylko dlatego, że można to zrobić - nie oznacza, że ​​powinieneś :)

Edycja: Ciąg dalszy ze względu na dodatkowe pytanie.

50k działało, ale spadło 60 tys., Więc gdzieś tam na moim stanowisku testowym.

Jeśli chodzi o to, jak to połączyć z wartościami bez użycia dużej klauzuli, osobiście utworzę tabelę tymczasową, wstawię wartości do tej tabeli tymczasowej, zindeksuj ją i wykorzystam w złączeniu, nadając mu najlepsze możliwości optymalizacji połączeń. (Generowanie indeksu na tabeli tymczasowej utworzy dla niego statystyki, które z reguły pomogą optymalizatorowi, chociaż 1000 identyfikatorów GUID nie uzna statystyk za zbyt użytecznych).

+1

patrz aktualizacja. dzięki za testowanie +1 – BuddyJoe

+0

Niestety, te sekwencje będą się dziać regularnie. Nie sądzę, że indeksowanie tabeli tymczasowej jest możliwe. W przypadku maksymalnych szybkich wstawień główna tabela będzie indeksowana przez int 'addid' (nie będzie indeksowana na GUID). Te rzeczy są trudniejsze, niż myślałem. – BuddyJoe

+1

Ryzykujesz niewielką przedwczesną optymalizacją - musisz zdobyć twarde, oprzyrządowane dane liczbowe w kategoriach planów zapytań dotyczących obciążenia pracą, ponieważ będzie to trudne do modelowania. Znając liczby różnych podejść, możesz dokonać wyboru, ale wstawienie 1k wierszy do tabeli temp. SQL może zostać wykonane wyjątkowo szybko, to naprawdę zależy od tego, jak/co je napędza. – Andrew

7

można załadować GUID do tabeli zarysowania następnie zrobić

... WHERE var IN SELECT guid FROM #scratchtable 
+0

Jeśli zakładasz, że masz te pytania co sekundę lub dwie. Zastanawiam się, jak wytrzyma stół do drapania. – BuddyJoe

+2

Używamy tej techniki extensivley w naszej aplikacji i wygląda na to, że działa dobrze. Tempdb musi być duży, a my dokonujemy pewnych zmian w instalacji - nie znam szczegółów tego. Tempdb robi się zajęty. – DaveE

Powiązane problemy