2012-06-22 12 views
5

Zastanawiam się tylko, czy liczba identyfikatorów na liście wpłynie na wydajność zapytań.SQL NOT IN [lista identyfikatorów] (wydajność)

przykład zapytania:

SELECT * FROM foos WHERE foos.ID NOT IN (2, 4, 5, 6, 7) 

Gdzie (2, 4, 5, 6, 7) jest nieskończenie rosnącej listy.

A ile jest za dużo (w kontekście kolejności)?

AKTUALIZACJA: Powód dlaczego pytam, ponieważ mam dwa db. Na nim (tylko do odczytu) jest źródłem przedmiotów, a drugi zawiera elementy przetwarzane przez operatora. Za każdym razem, gdy operator prosi o nowy element z bazy danych tylko do odczytu, chcę wykluczyć element, który jest już przetwarzany.

+14

Nie powinieneś również oznaczyć tę DB2? A co na ziemi jest "nieskończenie rowkowane"? Czy powinienem się bać czy podekscytować? –

+0

@AaronBertrand Wiem, przepraszam, ale trochę mnie to dręczyło, biorąc pod uwagę tytuł Mysql, ale potem dodano każdy tag RDBMS. – Taryn

+1

Twoje pytanie przypomina pytanie "Przy jakiej prędkości jazda jest odwrotna, niebezpieczna?" W takim przypadku jest wiele sposobów na uzyskanie tego, o co prosisz, ale prawdopodobnie będziemy bardziej pomocni, jeśli podasz * faktyczny * powód żądania. – swasheck

Odpowiedz

8

Tak, liczba identyfikatorów na liście będzie miała wpływ na wydajność. Pakiet sieciowy jest tylko tak duża, na przykład, a baza danych musi przeanalizować cały ten szum i przekształcić go w serii:

WHERE foo.ID <> 2 
AND foo.ID <> 4 
AND foo.ID <> 5 
AND ... 

Należy rozważyć inne sposoby pozwalające zapytanie o tym zestawie.

+4

dla "NOT IN" to byłoby to "AND", nie "OR" Myślę, że ... – JNK

+2

Tak, bardzo prawdziwe. Ale nie o to chodzi. :-) –

2

Oto głupi przepisać tej kwerendy, która może wykonać trochę lepiej

SELECT * FROM foos 
LEFT JOIN 
(
    SELECT 2 id UNION 
    SELECT 4 UNION 
    SELECT 5 UNION 
    SELECT 6 UNION 
    SELECT 7 
) NOT_IDS 
USING (id) WHERE NOT_IDS.id IS NULL; 

Podzapytanie NOT_IDS działa jak pokazano brzmienie:

mysql> SELECT * FROM 
    -> (
    ->  SELECT 2 id UNION 
    ->  SELECT 4 UNION 
    ->  SELECT 5 UNION 
    ->  SELECT 6 UNION 
    ->  SELECT 7 
    ->) NOT_IDS; 
+----+ 
| id | 
+----+ 
| 2 | 
| 4 | 
| 5 | 
| 6 | 
| 7 | 
+----+ 
5 rows in set (0.00 sec) 

mysql> 
+0

Czy zostanie to przetłumaczone przez MySQL w inny sposób niż istniejące zapytanie? Wyobrażam sobie, że oszałamiająca część nadal będzie budować tę wewnętrzną "UNION", w zależności od źródła listy. Ale w mojej głowie to nadal tłumaczy się na 'id <> 2 AND id <> 4 AND id <> 5 AND id <> 6 AND id <> 7' ... –

2

Tak dla zabawy, a dany aktualizacją , Zamierzam zasugerować inną strategię:

Możesz dołączyć do tabel tak jak ...

insert into db1.foos (cols) 
    select cols 
    from db2.foos src 
    left join db1.foos dst 
    on src.pk = dst.pk 
    where dst.othercolumn is null 

Nie jestem pewien, w jaki sposób optymalizator sobie z tym poradzi lub czy będzie to szybsze (zależy to od strategii indeksowania, jak sądzę) od tego, co robisz.

0

Bazy danych znajdują się na tym samym serwerze? Jeśli tak, możesz utworzyć kwerendę wielodostępową z lewostronnym sprzężeniem i przyjąć wartości zerowe. (tutaj przykład: Querying multiple databases at once). W przeciwnym razie możesz wykonać procedurę składowaną, przekazać id za pomocą ciągu znaków i podzielić je wewnątrz za pomocą wyrażenia regularnego. Mam podobny problem, ale w bazie danych db i postgres db. Na szczęście moja sytuacja jest (In ...)

Powiązane problemy