Abfrage mit verketteten OR-Verknüpfungen bringt MySQL zum Absturz..

WaterIT

Benutzer
Beiträge
12
Hallo alle zusammen,

Ich versuche folgende Abfrage zu machen:

Code:
SELECT daten.s0 AS parent_id, daten.s1 AS kunden_nr, daten.s2 AS kunde, dateien.* FROM dateien, daten WHERE (daten.s0 = 'oksur-68930' OR daten.s0 = 'lwgtv-08945' OR daten.s0 = 'gjqfd-68005' OR daten.s0 = 'zsdgt-22330' OR daten.s0 = 'cgdasr-45670' OR daten.s0 = 'tttss-21502' ) AND daten.s49="RG" AND daten.id=dateien.id AND dateien.geloescht="n" AND dateien.bezeichnung LIKE("%Protokoll");

Wie man sehen kann, habe ich direkt nach dem WHERE mehrere verkettete ORs. Bei 4 ORs hintereinander funktioniert die Abfrage. Bei dem 5. OR hängt sich der Server auf.. Wenn ich das LIKE ganz am Ende weglasse, funktionieren auch 5 ORs, beim 6. hängt er sich wieder auf..

Die MySQL Version ist 8.0.

Hat jemand einen Lösungsvorschlag? Vielen Dank im Voraus!

MfG,
WaterIT
 
Werbung:
Ich gehe mal davon aus "Server hängt sich auf" bedeutet in Deinem Fall nicht, dass der Server nicht mehr funktioniert (das wäre schon aussergewöhnlich) sondern einfach nur, dass Du ewig kein Resultat angezeigt bekommst?

Probier doch mal statt dem Endlos-OR die Werte mit einer einfachen IN-Abfrage abzufragen:
WHERE daten.s0 IN ('A','B','C')
 
Bei dem 5. OR hängt sich der Server auf.

Na, das glaube ich nicht.

1) Welche Fehlermeldung gibt es ?
2) Wie sieht das EXPLAIN aus ?

Kann es sein das da kein oder falsche Indexe vorhanden sind ?

Gruß

Bernd

verkürz das ganze mal so:
Code:
SELECT daten.s0 AS parent_id, daten.s1 AS kunden_nr, daten.s2 AS kunde, dateien.* FROM dateien, daten
WHERE
daten.s0 IN( 'oksur-68930', 'lwgtv-08945', 'gjqfd-68005', 'zsdgt-22330', 'cgdasr-45670', 'tttss-21502' )
 AND daten.s49="RG"
 AND daten.id=dateien.id
 AND dateien.geloescht="n"
 AND dateien.bezeichnung LIKE("%Protokoll");

Und Joins solltest du IN JEDEM FALL ausschreiben
 
Vielen Dank für die Antwort.

Dadurch, dass das Abfragen eine "Ewigkeit" dauert, ist der Server dann irgendwann nicht mehr erreichbar und ich muss es neustarten.
Ich habe die Abfrage mit der IN()-Funktion versucht. Da passiert leider genau das gleiche.. ab 4 verschiedenen Inhalten sucht der sich wieder tot..

Eine Fehlermeldung tritt nicht direkt auf. Er sucht auch ständig weiter. Aber wenn ich es stoppe (Nach 20 Sekunden ca) funktionieren keine weiteren Abfragen. Auch die anderen Mitarbeiter hier in der Firma können nicht mehr auf die DB zugreifen, bis es ich den MySQL-Dienst neustarte.
 
Dann schick doch mal das Ergebnis von

Code:
EXPLAIN SELECT daten.s0 AS parent_id, daten.s1 AS kunden_nr, daten.s2 AS kunde, dateien.* FROM dateien, daten
WHERE
daten.s0 IN( 'oksur-68930', 'lwgtv-08945', 'gjqfd-68005', 'zsdgt-22330', 'cgdasr-45670', 'tttss-21502' )
 AND daten.s49="RG"
 AND daten.id=dateien.id
 AND dateien.geloescht="n"
 AND dateien.bezeichnung LIKE("%Protokoll");

und verrat uns mal die Anzahl der Rows in den Tabellen
 
nöööö, aber ein LIKE mit "%" am Anfang vom Pattern bedeutet immer einen FULL TABLE SCAN, also MUSS MySQL alle Rows lesen,
ich denke aber das es an fehlenden Indexen liegt. Wir man aber sehen wenn das EXPLAIN kommt
 
Ich habe gerade versucht, einen Index zu erstellen. Leider dauert die Abfrage so lange, bis er sich wieder aufgehängt hat (Server unerreichbar und Fehlermeldung: Error Code: 2013 Lost connection to MySQL server during query)

Ich glaube wir haben einfach zu viele Daten, beim Index muss er ja auch erstmal alle Datensätze durchgehen und einen Index setzen. Wir haben für jeden Datensatz über 100 Spalten (ist historisch gewachsen).
 
Ich bin Werkstudent und habe leider nicht viel Ahnung von Server Konfiguration. Ich mache zwar Feierabend, bin aber morgen wieder da. Über weitere Hilfe würde ich mich sehr freuen. Danke schonmal im Voraus!
 
Es sind 472.187 rows von der Tabelle dateien.. das scheint echt viel zu sein.
Peanuts.

Code:
edb=*# create table dateien (id int, data1 text, data2 int, geloescht bool, bezeichnung text);
CREATE TABLE
edb=*# insert into dateien select (random()*1000000)::int, 'random value' || random()::text, (random()*1000)::int, false, (random()*10000)::text || 'Protokoll'  from generate_series(1,10000000);
INSERT 0 10000000
edb=*# create table daten(id int primary key, s0 text, s1 int, s2 text, s49 text);
CREATE TABLE
edb=*# insert into daten select s, (random()*10000)::text, (random()*1000000)::int, 'Kunde ' || s::text, (random()*100)::text from generate_series(1,10000000) s;
INSERT 0 10000000
edb=*# commit;
COMMIT

Also 10.000.000 in dateien und auch 10.000.000 in daten. Mal sehen, was passiert:

Code:
edb=*# explain analyse SELECT daten.s0 AS parent_id, daten.s1 AS kunden_nr, daten.s2 AS kunde, dateien.* FROM dateien, daten
WHERE
daten.s0 IN( 'oksur-68930', 'lwgtv-08945', 'gjqfd-68005', 'zsdgt-22330', 'cgdasr-45670', 'tttss-21502' )
 AND daten.s49='RG'
 AND daten.id=dateien.id
 AND dateien.geloescht= false
 AND dateien.bezeichnung LIKE('%Protokoll');
                                                                       QUERY PLAN                                                                       
--------------------------------------------------------------------------------------------------------------------------------------------------------
 Gather  (cost=172353.59..358980.35 rows=1499 width=135) (actual time=703.816..784.384 rows=0 loops=1)
   Workers Planned: 2
   Workers Launched: 2
   ->  Parallel Hash Join  (cost=171353.59..357830.45 rows=625 width=135) (actual time=668.462..668.465 rows=0 loops=3)
         Hash Cond: (dateien.id = daten.id)
         ->  Parallel Seq Scan on dateien  (cost=0.00..175540.42 rows=4166257 width=67) (never executed)
               Filter: ((NOT geloescht) AND (bezeichnung ~~ '%Protokoll'::text))
         ->  Parallel Hash  (cost=171348.17..171348.17 rows=433 width=72) (actual time=668.260..668.261 rows=0 loops=3)
               Buckets: 2048  Batches: 1  Memory Usage: 0kB
               ->  Parallel Seq Scan on daten  (cost=0.00..171348.17 rows=433 width=72) (actual time=668.221..668.221 rows=0 loops=3)
                     Filter: ((s49 = 'RG'::text) AND (s0 = ANY ('{oksur-68930,lwgtv-08945,gjqfd-68005,zsdgt-22330,cgdasr-45670,tttss-21502}'::text[])))
                     Rows Removed by Filter: 3333333
 Planning Time: 0.628 ms
 JIT:
   Functions: 45
   Options: Inlining false, Optimization false, Expressions true, Deforming true
   Timing: Generation 9.329 ms, Inlining 0.000 ms, Optimization 2.281 ms, Emission 46.006 ms, Total 57.617 ms
 Execution Time: 788.715 ms
(18 rows)

edb=*#

Also Ergebniss nach 788 Millisekunden. Natürlich entsprechen meine Daten nicht Deinen, daher ist der Vergleich nicht so wirklich sinnvoll. Andererseits auch noch keine Indexe (außer den impliziet erzeugten auf daten.id wegen Primary Key.
 
Es gibt ja nicht nur die DB Konfiguration, sondern auch eine Hardware, das kann von Raspberry bis zum Multicore Number Cruncher gehen.
Aber was ich sagen wollte:
Wie sieht das Datenmodell aus? Ist das ein reguläre Foreign Key auf dem Du joinst? Also 1:N?
Und wenn ja, glaubst Du, dass es so ist oder weißt Du es? Hast Du es geprüft?
Wenn Du die Abfrage ohne Daten laufen lässt nur auf Dateien, mit der gezeigten Einschränkung, wieviel Datensätze ergibt es bzw. wieviel ID ergibt es mit welcher Anzahl?
 
Ich antworte jetzt soweit, wie ich die Fragen verstanden habe:
Ich habe eine Tabelle daten mit dem PK id und eine Tabelle dateien mit dem PK id und dateiid, also ein zusammengesetzter PK.
Ich brauche die id der Tabelle daten, um an die entsprechenden dateien zu kommen. Deshalb kann ich leider nicht auf die Tabelle daten in der Abfrage verzichten. Wenn ich aber SELECT * FROM dateien abfrage, zeigt der mir sofort alle Ergebnisse an (Der geht dann ohne Probleme alle 471.198 Zeilen durch).

Die genannten Informationen kann ich alle in der Datenbank einsehen, habe es also geprüft.

Ich hoffe, ich konnte die Fragen ausreichend beantworten. Ich habe vorher nichts mit Datenbanken zu tun gehabt, und studiere auch nicht direkt in dieser Richtung, weshalb ich leider kein tiefes Wissen habe in diesem Bereich.. Aber ich lerne gerne dazu. Und eure Antworten helfen mir dabei, dafür möchte ich mich jetzt schonmal bedanken.

Ergänzung: jede parent_id (also daten.s0) kann mehrere Ergebnisse in der Tabelle dateien liefern. Aber die id in daten und die id und dateien sind eindeutig. Ich glaube deshalb, dass das eine 1:N Abfrage ist, oder?
 
Werbung:
Aber die id in daten und die id und dateien sind eindeutig
Du könntest einfach die Create Statements der Tabellen zeigen, dann wäre das klar.
Alternativ kannst Du diese Abfragen laufen lassen:
Code:
SELECT e.id, count(*)
  FROM dateien e
 WHERE e.geloescht = "n"
   AND e.bezeichnung LIKE ("%Protokoll");
 group by e.id
having count(*)>1;

SELECT a.id, count(*)
  FROM daten a
 WHERE (a.s0 = 'oksur-68930' OR a.s0 = 'lwgtv-08945' OR
        a.s0 = 'gjqfd-68005' OR a.s0 = 'zsdgt-22330' OR
        a.s0 = 'cgdasr-45670' OR a.s0 = 'tttss-21502')
   AND a.s49 = "RG"
 group by a.id
having count(*)>1;
Es sollte eine leere Menge ergeben.
 
Zurück
Oben