# Frage zu SQL "WHERE IN (1, 2, 3. , N)"



## Guest (15. Aug 2008)

Hallo,

ich komme leider nicht drumherum, SQL-Abfragen mit einem IN - Statement zu machen, wobei die Anzahl des Arrays für dieses IN-Statement leider sehr hoch ist ( > 1500 ). Jetzt habe ich schon mehrfach nachgelesen, das ein IN-Statement bei Arraygrößen > 100 nicht sehr performant arbeitet.

Meine Frage dazu wäre: Macht es Sinn, die Abfrabe auf mehrere zu verteilen (also immer mit jeweils 100 Datensätzen, die ich in der IN-Klausel prüfe) ? Würden sich hierzu PreparedStatements anbieten, oder hat das hier üerhaupt keinen Effekt? Macht es auch evtl. Sinn das Array zu sortieren, oder ist es für die Ausführungsgeschwindigkeit des SQL völlig egal, in welcher Reihenfolge meine ID´s  in das IN-Statement geschoben werden? (Es handelt sich hierbei um Primary Keys aus einer anderen Tabelle).

Vielen Dank im Vorraus!

Gruß
Christian


----------



## foobar (15. Aug 2008)

Eine In-Klausel mit 1500 Elementen? Das kommt mir spanisch vor. 

Kannst du das nicht mit einem Join oder Subselect lösen? Oder vielleicht mit einer temporären Tabelle?


----------



## Det (15. Aug 2008)

Bei manuellen Abfragen habe ich schon festgestellt, dass manche Datenbanken nur eine gewisse Anzahl von Elementen bei IN verarbeiten können. Ich muss dazu sagen, dass ich da zu faul zum Nachdenken war und lieber mit Copy/Paste gearbeitet habe. Denn normalerweise sollte man versuchen, hier ein JOIN (ohne T  ) zu basteln. Ich nehme ja an, dass du die Werte in  deinem Array auch per SELECT ermittelt hast. Falls ein direkter JOIN nicht möglich ist, könnte man die Werte vielleicht (in mehrere Schritten, falls nötig) in eine temporäre Tabelle schieben und damit joinen.

Also statt


```
SELECT ... FROM tabelle1 WHERE bedingung1
==> liste
SELECT ... FROM tabelle2 WHERE id IN [liste]
```
irgendwas wie

```
SELECT tabelle2... FROM tabelle1, tabelle2 WHERE tabelle1.fk_feld = tabelle2.id AND tabelle1.bedingung1
```
oder

```
SELECT id INTO temp FROM tabelle1 WHERE bedingung1
SELECT id INTO temp FROM tabelle1 WHERE bedingung2
...
SELECT tabelle2... FROM temp, tabelle2 WHERE temp.id = tabelle2.id
```


----------



## Guest (15. Aug 2008)

Hallo!

Danke für eure schnellen Antworten.

Leider kann ich das so nicht umsetzen, denn das Array für mein IN kommt aus einem JAVA-Array und wird nicht durch eine DB-Query ermittelt. Die ID´s in diesem Array sind Primärschlüssel einer anderen Tabelle. 

Oder gibt es da dennoch eine Möglichkeit? Leider fehlt mir das entsprechende Know-How, ich hatte bisher noch nie etwas mit temporären Tabellen zu tun.


----------



## byte (15. Aug 2008)

Teil das Array doch einfach auf. Also aus einem langsamen Select machst Du viele schnelle.


----------



## SlaterB (15. Aug 2008)

und zurück zur eigentlichen Frage:
das IN dürfte so langsam sein, weil so viele Vergleiche durchzuführen sind,
mehrere kleinere INs in einer Query sind demnach genauso langsam, die Anzahl der Vergleiche bleibt gleicht


----------



## semi (15. Aug 2008)

SlaterB hat gesagt.:
			
		

> das IN dürfte so langsam sein, weil so viele Vergleiche durchzuführen sind,
> mehrere kleinere INs in einer Query sind demnach genauso langsam, die Anzahl der Vergleiche bleibt gleicht


Ist das eine Feststellung oder eine Frage ohne Fragezeichen?  Das ganze geht schnell bei indizierten Feldern.

Nur mal so als Warnung, bei Oracle liegt das Limit bei 1000 Einträgen in der IN-Klausel.


----------



## SlaterB (15. Aug 2008)

eine Vermutung und jede DB wäre schön doof, wenn sie große INs nicht automatisch in mehrere kleine aufspaltet, falls das schneller ginge


----------



## Det (19. Aug 2008)

Anonymous hat gesagt.:
			
		

> ... das Array für mein IN kommt aus einem JAVA-Array und wird nicht durch eine DB-Query ermittelt. Die ID´s in diesem Array sind Primärschlüssel einer anderen Tabelle.
> 
> Oder gibt es da dennoch eine Möglichkeit? Leider fehlt mir das entsprechende Know-How, ich hatte bisher noch nie etwas mit temporären Tabellen zu tun.



Statt einer temporären Tabelle kann man dafür sicher auch eine "normale" Tabelle verwenden. 

Auf Java-Ebene kann man da übrigens auch eine Menge Zeit vertrödeln, z.B. je nachdem wie man aus dem Array den SQL-String zusammenbaut. Ich würde deshalb zunächst einfach mal direkt mit SQL ausprobieren, was schneller ist:

a) deine bisherige Lösung mit IN
b) Tabelle anlegen, die nur ein Feld für die IDs enthält - IDs einfügen - Abfrage mit JOIN über beide Tabellen ausführen


----------

