Größe der Query reduzieren

kwakz

Aktiver Benutzer
Beiträge
29
Hallo zusammen,

für eine Ventilproduktion werden die Produktionsdaten in einer Datenbank abgelegt. In Tabelle 1 gibt es die Zuordnung einer ID zu Produktionsdatum, Ventiltyp, Teilbewertung und anderen Punkten. In verschiedenen anderen Tabellen bekomme ich über die ID Informationen über Messwerte, Parametersätze und dergleichen.

Um mir jetzt meine Messwerte herauszusuchen, mache ich nunächst eine abfrage, welche IDs in einem bestimmten Zeitraum produziert wurden. Diese IDs verknüpfe ich dann mit einem 'OR' und suche dann in den anderen Tabellen. Das funktioniert bei kurzen Zeiträumen auch ganz gut. Mache ich den Zeitraum aber länger, dann bekomme ich zwar noch meine IDs für den Zeitraum, bei der Abfrage der Messwerte kommt aber die Fehlermeldung:

Exception occured in Microsoft OLE DB Provider for SQL Server: Interner Fehler: Ein Ausdrucksdienstelimit wurde erreicht. Suchen Sie nach potenziell komplexen Ausdrücken in Ihrer Abfrage, und vereinfachen Sie sie.

Ich nehme an, dass ich einfach versuche zu viele IDs miteinander zu verknüpfen ... ich habe auch schon irgendwo die Information gefunden, dass die Anfrage nicht mehr als 65000 Zeichen haben darf (was bei einer Produktion von mehreren tausend Ventilen am Tag aber ganz schnell zusammen kommt).

Jetzt die Frage: Wie kann ich die Anfrage vereinfachen? Gibt es zum Beispiel eine Möglichkeit, dass ich mir die gefundenen IDs in einer Liste ablege und bei der Abfrage der Messwerte dann sage: "Tu das für alle IDs, die in der Liste stehen"?

Mfg Daniel
 
Werbung:

akretschmer

Datenbank-Guru
Beiträge
9.830
Jetzt die Frage: Wie kann ich die Anfrage vereinfachen? Gibt es zum Beispiel eine Möglichkeit, dass ich mir die gefundenen IDs in einer Liste ablege und bei der Abfrage der Messwerte dann sage: "Tu das für alle IDs, die in der Liste stehen"?

Mfg Daniel

Du kannst das zu einem JOIN umschreiben oder zu einem Subselect. Versuch es mal.

Also z.B. select bla, fasel from table2 where id in (select id from foobar where datum = ...)
 

ukulele

Datenbank-Guru
Beiträge
4.702
Solange nicht zu jeder ID ein eigenes Resultat geliefert werden soll (bei OR Verknüpfungen wird ja auch nur eine Abfrage erstellt) sollte das auf jedenfall mit Join oder Subselect gehen. Wenn du es nicht hinbekommst musst du die Abfragen mal posten.

Die OR Variante dürfte aber eigentlich auch nicht viel langsammer sein, eventuell besteht hier auch noch ein anderes Problem.
 

kwakz

Aktiver Benutzer
Beiträge
29
Hallo zusammen,

schon mal vielen Dank für die Antworten. Ihr habt mir schon mal ein Stück weiter geholfen. Allerdings hilft mir das noch nicht bis ganz an's Ziel: Zwischendurch bearbeite ich meine IDs auch nach Gesichtspunkten, die so nicht in der Datenbank zu finden sind. Danach muss ich quasi mit den OR-verknüpften IDs die nächsten Abfragen machen. Habt Ihr dafür auch eine Lösung für mich?

Mfg Daniel
 

akretschmer

Datenbank-Guru
Beiträge
9.830
Hallo zusammen,

schon mal vielen Dank für die Antworten. Ihr habt mir schon mal ein Stück weiter geholfen. Allerdings hilft mir das noch nicht bis ganz an's Ziel: Zwischendurch bearbeite ich meine IDs auch nach Gesichtspunkten, die so nicht in der Datenbank zu finden sind.

Das klingt abentuerlich ...

Danach muss ich quasi mit den OR-verknüpften IDs die nächsten Abfragen machen. Habt Ihr dafür auch eine Lösung für mich?

Mfg Daniel


Geht es besser, wenn Du die ID's einfach in eine neue Tabelle schreibst und damit arbeitest?
 

ukulele

Datenbank-Guru
Beiträge
4.702
Man kann auch statt ID = 1 OR ID = 2 mit ID IN (1,2) arbeiten aber an der eigentlichen Geschwindigkeit dürfte das nicht viel ändern. Interessant dürfte es bei der Anzahl der IDs im Query und in der Tabelle werden und ob es einen Index auf die ID Spalte gibt.
 

akretschmer

Datenbank-Guru
Beiträge
9.830
Man kann auch statt ID = 1 OR ID = 2 mit ID IN (1,2) arbeiten aber an der eigentlichen
Geschwindigkeit dürfte das nicht viel ändern.

Depends.

Das kann durchaus in unterschiedlichen Plänen ausarten:

Code:
test=*# explain select * from foo where id=1 or id=2 or id=3;
  QUERY PLAN
--------------------------------------------------------------------------
 Bitmap Heap Scan on foo  (cost=13.05..23.68 rows=36 width=4)
  Recheck Cond: ((id = 1) OR (id = 2) OR (id = 3))
  ->  BitmapOr  (cost=13.05..13.05 rows=36 width=0)
  ->  Bitmap Index Scan on idx1  (cost=0.00..4.34 rows=12 width=0)
  Index Cond: (id = 1)
  ->  Bitmap Index Scan on idx1  (cost=0.00..4.34 rows=12 width=0)
  Index Cond: (id = 2)
  ->  Bitmap Index Scan on idx1  (cost=0.00..4.34 rows=12 width=0)
  Index Cond: (id = 3)
(9 rows)

test=*# explain select * from foo where id in (1,2,3);
  QUERY PLAN
--------------------------------------------------------------------
 Bitmap Heap Scan on foo  (cost=5.03..15.53 rows=36 width=4)
  Recheck Cond: (id = ANY ('{1,2,3}'::integer[]))
  ->  Bitmap Index Scan on idx1  (cost=0.00..5.02 rows=36 width=0)
  Index Cond: (id = ANY ('{1,2,3}'::integer[]))
(4 rows)


Andreas
 

kwakz

Aktiver Benutzer
Beiträge
29
Da hab ich mich vielleicht nicht ganz richtig ausgedrückt. Es ist halt so: Ich reduziere meine IDs in mehreren Schritten, wobei die Gesichtspunkte für diese Schritte in verschiedenen Tabellen abgelegt sind. Als Beispiel:

1. Nimm alle IDs, die innerhalb eines bestimmten Zeitraums gebaut wurden und die Bewertung OK bekommen haben.
2. Aus diesen IDs sortiere die aus, die nicht im ersten Durchlauf auf der Anlage sind, sondern schon nachbearbeitet wurden
3. Aus den resultierenden IDs sortiere die aus, die nicht in einem bestimmten Testmodul getestet wurden.

Im Prinzip steht für jeden Punkt die Information in einer anderen Tabelle. Die Verarbeitungsschritte mache ich in einem LabVIEW-Programm, was dann mit den reduzierten IDs wieder auf die nächste Tabelle zugreifen muss.

Für die Datenbank selbst habe ich leider nur Leserechte ... damit fällt das Anlegen einer neuen Tabelle flach.
 

ukulele

Datenbank-Guru
Beiträge
4.702
Und hast du schon eine Abfrage noch dem Motto
Code:
SELECT   *
FROM   tabelle
WHERE   ID IN (   SELECT   ID
         FROM   tab_bauzeit
         WHERE   bauzeit BETWEEN x AND y
         AND     bewertung = 'OK' )
AND     ID NOT IN (   SELECT   ID
           FROM   tab_durchlauf
           WHERE   ... )
AND     ID NOT IN (   SELECT   ID
           FROM   tab_testmodul
           WHERE   ... )
ausprobiert?
 

kwakz

Aktiver Benutzer
Beiträge
29
Daran probier ich mich gerade ... in der Therorie müsste ich ja in jeder Tabelle mit der gleichen Abfrage (natürlich abgesehen von den ersten beiden Zeilen) die gleichen IDs herausbekommen ... aktuell ist dem aber nicht so. da werde ich wohl noch ein bisschen knobeln müssen
 
Werbung:

ukulele

Datenbank-Guru
Beiträge
4.702
Daran probier ich mich gerade ... in der Therorie müsste ich ja in jeder Tabelle mit der gleichen Abfrage (natürlich abgesehen von den ersten beiden Zeilen) die gleichen IDs herausbekommen ... aktuell ist dem aber nicht so. da werde ich wohl noch ein bisschen knobeln müssen
Raff ich nicht. Jede Unterabfrage muss eine Liste mit IDs liefern. Ob die ID in der Liste steht prüft die Abfrage selbst.

Einzig zu beachten ist das bei einer Unterabfrage mit kein NULL Wert in der id Spalte stehen darf, das dürfte aber eh nicht der Fall sein.
 
Oben