![]() |
Datenbank: MySQL • Version: 5 • Zugriff über: UniDac
Doppel-Select-Anweisung zu langsam
Hallo Zusammen,
ich habe eine Tabelle mit ca 500.000 Datensätzen. Dort mache ich so eine Abfrage:
Delphi-Quellcode:
Ich mache die Abfrage deshalb so, weil es Aufträge gibt, bei denen nicht alle in 2012 abgeschlossen wurden, sondern nur die letzten. Von diesen Aufträgen möchte ich aber alle Arbeitsgänge mit rausbekommen.
Select * from Tabelle1 where SpalteA in (
Select SpalteA from Tabelle1 where SpalteDatum between '20120101' and '20121231') Leider schmiert mit der MySQL-Server bei dieser Abfrage ab. Wie würdet Ihr das lösen? Vielen Dank Patrick |
AW: Doppel-Select-Anweisung zu langsam
Jetzt krieg ich wieder Haue weil ich keine Ansi-Joins verwende
Code:
Gruß
select *
from Tabelle1 ,(select spalteA from Tabelle1 where Bedingung) BedTable where Tabelle1.Spaltea=BedTable.Spaltea K-H |
AW: Doppel-Select-Anweisung zu langsam
Hallo,
leider bringt auch diese Anweisung nach mehreren Minuten noch kein Ergebnis... Ist das so kompliziert für den SQL-Server oder warum funktioniert das nicht in einer halbwegs vernümftigen Zeit??? Gruß Patrick |
AW: Doppel-Select-Anweisung zu langsam
So müsste es auch gehen, wenn ich keinen Denkfehler mache:
SQL-Code:
Ggf. noch Indizes auf SpalteA und SpalteDatum setzen.
SELECT
A.* FROM Tabelle1 A JOIN Tabelle1 B ON B.SpalteA = A.SpalteA WHERE B.SpalteDatum BETWEEN '20120101' AND '20121231' |
AW: Doppel-Select-Anweisung zu langsam
Was mache ich hier nur???
Auch diese Lösung bringt nach mehreren Minuten kein Ergebnis... Gruß Patrick |
AW: Doppel-Select-Anweisung zu langsam
Wieviele Datensätze sind denn das insgesamt? Und stimmt das Datumsformat? Ich bin gerade nicht mehr sicher, wie das unter MySQL auszusehen hat, hast Du es mal mit SQL-Parametern probiert? Sind Indizes vorhanden?
|
AW: Doppel-Select-Anweisung zu langsam
Ich behaupte mal, das SQL Statement ist 2.rangig. Schließlich ist MySQL nicht mehr Version 2.0 doer so..
Die Indizierung ist entscheidend. Und was bedeutet "abschmieren", so ist das halt by full table scan ohne indizierung (Vermutung). Ok, vielleicht ist der mySQL optimizer tatsächlich so gestrickt. Notfalls mit dem Range select eine Temp Table bauen und die dann weiterverwenden, macht nur 2 Full Table scans. |
AW: Doppel-Select-Anweisung zu langsam
Jetzt hat sich der MySQL-Server vollendst abgeschossen...
Ich versuche es später. Vielen Dank erst mal Gruß und schönen Abend Patrick |
AW: Doppel-Select-Anweisung zu langsam
einfach mal die Statement Varianten mit
Code:
oder
explain [mysqlstatement]
Code:
aufrufen.
explain extended [mysqlstatement]
Ach nochwas, falls deine Spalte A (das Hauptjoinkriterium also?) offenbar nicht eindeutig ist, sondern nur sowas wie ein Gruppenschlüssel, solltest Du je nach Statement variante aus den vorschlägen noch ein 'distinct' oder 'group by' spendieren, sonst explodiert das Volumen tatsächlich, bei 500T Sätzen sicher unangenehm. Möglicherweise fallen Dir ja auch noch andere Kriterien ein, die das ganze etwas eindampfen. |
AW: Doppel-Select-Anweisung zu langsam
Ich würde mir mal den Server genauer anschauen:
|
AW: Doppel-Select-Anweisung zu langsam
"In" ist extrem teuer (Zeitaufwand).
Ich würde die Abfrage in eine View für das Auswahlkriterium
Code:
und in die eigentliche Datenabfrage aufteilen:
/* Index über SpalteDatum erforderlich */
CREATE VIEW V_SpalteA2012( SpalteA) AS Select SpalteA from Tabelle1 where SpalteDatum between '20120101' and '20121231';
Code:
/* Index über SpalteA erforderlich */
select b.* from V_SpalteA2012 a left join Tabelle1 b on b.SpalteA = a.SpalteA |
AW: Doppel-Select-Anweisung zu langsam
Auch wenn der TE scheinbar einen Herzanfall hatte oder noch dabei ist, den Server wieder betriebsbereit zu machen:
Das ist nun das "vermutlich" 3. verschlimmbesserte Statement, deshalb bitte noch mal meinen vorigen Beitrag berücksichtigen. "Vermutlich" deshalb, weil ein paar Detailangaben des TE fehlen. Sein ursprüngliches SQL ist hier sehr wahrscheinlich das einzig formal richtige, das implizit (durch das IN) ein Distinct auf die Menge macht. Alle anderen Statements machen das nicht und würden bei einer Grundmenge von 500T Sätzen solange daten permutieren, bis der Tablespace voll ist. Distinct wäre also bei den beiden Vorschlägen zu ergänzen. Ich würde den von p80286 plus Distinct im Subselect nehmen. Und Views bringen hier eher keinen Geschwindigkeitsvorteil. |
AW: Doppel-Select-Anweisung zu langsam
Ich werfe es jetzt mal einfach in den Raum:
Wir hatten letzte Woche auch Performanceprobleme mit MySQL. Eine stinknormale Abfrage hat trotz richtiger Indizierung usw. ungewöhnlich lange gedauert. Dieses Problem lies sich mit mehreren Datenbeständen (Kunden) und mehreren MySQL-Versionen reproduzieren. Ich habe dann mal eine Migration zu MariaDB (hat ca. 10 Minuten gedauert) durchgeführt. Bei MariaDB dauert exakt der selbe Befehl nur noch 0.0x Sekunden. Wir stampfen MySQL jetzt ein und verwenden nur noch MariaDB. Am Code mussten wir übrigens nichts ändern, da war MariaDB tatsächlich 100%ig kompatibel. |
AW: Doppel-Select-Anweisung zu langsam
Zitat:
Zitat:
Zitat:
|
AW: Doppel-Select-Anweisung zu langsam
@MAriaDB
Mmh, ich arbeite nicht produktiv mit mySQL. Aber die Erfahrung zeigt: Jedes RDBMS hat seine Schwächen, das sind ganz selten harte Fehler bei der SQL Auswertung, aber häufig "obskures" Verhalten der Optimizer. Hat man sich in einem System "eingearbeitet", also an seine Macken gewöhnt, kann man bezüglich der heimlichen Schwachstellen auch leicht vom Regen in die Traufe geraten. Einen solchen Schwenk würde ich nur nach gründlichen Tests machen. Andererseits ist ja im Zeitalter von JPA das RDBMS zur Blackbox verkommen und unschlaues SQL wird durch mehr Transistoren, SSD Cache & Co ersetzt. |
AW: Doppel-Select-Anweisung zu langsam
Zitat:
Ist natürlich kein Vergleich zum Problem vom TE, aber im Vergleich zu den 0.0x Sekunden auf MariaDB schon ziemlich krass. Das hat uns echt gewundert. Zitat:
Zitat:
|
AW: Doppel-Select-Anweisung zu langsam
Zitat:
Wir haben am Ende sogar ganz perverse Dinge versucht (IIFs anstatt Wheres,...) doch letztendlich war es definitiv ein Problem von MySQL. Wir waren auch ziemlich erstaunt, dass ein Fork so viel schneller ist. Btw. nachdem wir die Kunden auf MariaDB umgestellt haben, lief das gesamte Programm auch merklich schneller. Der Geschwindigkeitszuwachs beschränkt sich also nicht nur auf diese eine Abfrage! Wir sind seitdem begeistert... Vor allem weil es auch wirklich schnell umgestellt ist. Edit: Hier mal das SQL-Statement:
Code:
Unter MySQL: /* 0 rows affected, 1 rows found. Duration for 1 query: 7,753 sec. */
SELECT SUM(POSITIONEN.MENGE)
FROM POSITIONEN INNER JOIN BELEGE ON (POSITIONEN.BELEGNR = BELEGE.BELEGNR) WHERE POSITIONEN.ARTIKELNR = '1090213000' AND BELEGE.BELEGART = 'A' Unter MariaDB: /* 0 rows affected, 1 rows found. Duration for 1 query: 0,078 sec. */ Belegart, Artikelnr und Belegnr sind natürlich indiziert. |
AW: Doppel-Select-Anweisung zu langsam
Glaube ich gern, es wäre sonst ja etwas unverantwortlich.
Gerade bei MySQL und Maria ist ein Tausch ja auch naheliegend, auch bzw. vor allem ohne Nutzung von JPA/Hibernate. Maria würde im obigen Fall (SQL Alternativvorschläge) allerdings genauso die Daten permutieren. Korrektes SQL steht also erstmal am Anfang. |
AW: Doppel-Select-Anweisung zu langsam
Was natürlich sein kann: Beim MySQL die Community-Edition eingesetzt statt der Professional. Erstere ist in vielen Punkten (mehr oder weniger absichtlich) nicht so gut optimiert wie die Pro-Version. Soll wohl so ein orakelsches Marketing-Argument für das größere MySQL oder sogar OracleDB sein. Darum könnte ich mir denken, dass der Performance-Vergleich zwischen MySQL-Pro und MariaDB kaum noch nennenswerte Unterschiede zeigen würde.
|
AW: Doppel-Select-Anweisung zu langsam
Da hast du recht, wir haben hier nur den Community-Server.
Ich lade mir mal die Trial vom Enterprise-Server herunter und teste dann noch mal ;-) edit: wobei wir niemals einen kostenpflichtigen Server kaufen würden, wenn es den bei MariaDB "umsonst" gibt... |
AW: Doppel-Select-Anweisung zu langsam
So, Enterprise Server heruntergeladen und installiert.
Seltsamerweise ist der sogar noch langsamer als der Community-Server. Ich habe den SQL-Dump also ganz frisch auf dem Enterprise-Server eingelesen. Keine Daten(banken) übernommen! Vorsichtshalber habe ich die Abfrage gleich 3x hintereinander durchgeführt: Zitat:
MySQL Enterprise:
Code:
MariaDB:
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE POSITIONEN ref PRIMARY,artikelnr,belegnr artikelnr 53 const 16160 100.00 Using where 1 SIMPLE BELEGE eq_ref PRIMARY,belegart PRIMARY 52 POSITIONEN.belegnr 1 100.00 Using where
Code:
MariaDB macht also irgendwas anders als MySQL.
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE POSITIONEN ref PRIMARY,artikelnr,belegnr artikelnr 53 const 16160 100.00 Using index condition 1 SIMPLE BELEGE eq_ref PRIMARY,belegart PRIMARY 52 POSITIONEN.belegnr 1 100.00 Using where Kann man dieses Verhalten MySQL beibringen? ("USE INDEX" oder ähnliches?) |
AW: Doppel-Select-Anweisung zu langsam
Das geht ziemlich in die Interna, da müßte man wahrscheinlich mal direkt bei MariaDB anfragen. (Bei MySQL solltest du damit lieber nicht landen denke ich *gg*)
|
AW: Doppel-Select-Anweisung zu langsam
Nachtrag (grade erst gesehen):
![]() |
AW: Doppel-Select-Anweisung zu langsam
Ach, MariaDB läuft ja wie gesagt extrem schnell. Es gibt dort keinerlei Probleme, daher lassen wir es jetzt so wie es ist.
Es wundert mich aber sehr, dass so eine simple SQL-Abfrage so einen großen Unterschied wirft. Vor allem bei "Der populärsten Open-Source-Datenbank der Welt" ;-) Und im Zusammenhang mit der eigenen Client Library vom MariaDB (libmysql.dll), die unter LGPL lizensiert ist, fällt mir auch kein Grund ein, warum man sich noch den MySQL-Server von Oracle ins Haus holen sollte... |
AW: Doppel-Select-Anweisung zu langsam
Welche Datentypen werden hier benutzt?
In den Beispielen sehe ich immer nur Strings. Datum, Artikelnummer sind theoretisch schöne Zahlen, wo Computer prima Sortieren und Vergleichen können. Strings sind für Sortieren und Vergleichen eher schlecht. |
AW: Doppel-Select-Anweisung zu langsam
Zitat:
![]() Dein Vergleich ist glaub ich etwas unfair. Eine frische Datenbank hat idR. noch keine Statistiken aufgebaut und die Optimizer Entscheidungen können die Selektivität eines Index nicht berücksichtigen. Hab kein Plan, was man da bei mysql alles anwerfen muss, aber es sollte sich bei größeren Datenmengen schon lohnen, die Statistiken zu fahren. |
AW: Doppel-Select-Anweisung zu langsam
Zitat:
Ein Datum berücksichtige ich hier nicht. Zitat:
Bevor wir auf MariaDB umgestellt haben, lief die DB mehrere Jahre unter MySQL. Dort waren die Abfragen aber genauso langsam. Zitat:
Naja, nu ists aber auch egal, ist ja nicht mein Thema hier ;-) |
AW: Doppel-Select-Anweisung zu langsam
Zitat:
Zitat:
|
AW: Doppel-Select-Anweisung zu langsam
Zitat:
Alle SQL Statements außer dem des TE im ersten Post permutieren mit ziemlicher Sicherheit die Daten! Also aus 10 Datensätzen werden z.B. 25, aus 200 werden 2000 usw. Aus 5000000 wie beim TE werden vermutlich sehr sehr viele.. Zitat:
|
AW: Doppel-Select-Anweisung zu langsam
Du kannst die Artikelnummern Hashen und in einer zusätzlichen Spalte ablegen.
Diese dann Indizien und für den Join als erstes! Argument nutzen.
Code:
Mit dem Optimierer würde ich noch prüfen ob es Sinn macht, dass SQL auf SubQueries oder Left-Joins umzustellen.
SELECT SUM(POSITIONEN.MENGE) FROM POSITIONEN INNER JOIN BELEGE ON (POSITIONEN.BELEGTNRHASH=BELEGE.BELEGNRHASH and POSITIONEN.BELEGNR = BELEGE.BELEGNR) WHERE POSITIONEN.ARTIKELNR = '1090213000' AND BELEGE.BELEGART = 'A' ;
MYSQL neigt gelegentlich dazu kartesische Produkte zu bilden. Vielleicht so?
Code:
SELECT SUM(POSITIONEN.MENGE) FROM POSITIONEN
JOIN (select BELEGE.BELEGNRHASH, BELEGE.BELEGNR FROM BELEGE WHERE POSITIONEN.ARTIKELNR = '1090213000' AND BELEGE.BELEGART = 'A') abc on (POSITIONEN.BELEGTNRHASH=abc.BELEGNRHASH and POSITIONEN.BELEGNR = abc.BELEGNR) |
AW: Doppel-Select-Anweisung zu langsam
@Morphie
Nur so zum Spass, leg doch mal einen Index ArtikelBeleg an mit eben den beiden Spalten ArtikelNr, BelegNr (auch in der Reihenfolge wie in der Where Bedingung). Die Laufzeit und das Explain würden mich mal interessieren (von beiden). Ich vermute mal, dass MySQL jetzt schneller wird (weil es jetzt einen passenden Index zum Where gibt). Ob Maria da noch etwas zulegen kann ... |
AW: Doppel-Select-Anweisung zu langsam
Kein Vorteil...
Den Index habe ich so angelegt:
Code:
Der Plan sieht jetzt so aus:
ALTER TABLE `positionen` ADD INDEX `ArtikelBeleg` (`artikelnr`, `Belegnr`);
Code:
Er nimmt jetzt also den Index, aber irgendwie immer noch anders als bei MariaDB... Geschwindigkeitsvorteile gibt es auch keine
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE POSITIONEN ref PRIMARY,artikelnr,belegnr,ArtikelBeleg ArtikelBeleg 53 const 16140 Using where 1 SIMPLE BELEGE eq_ref PRIMARY,belegart PRIMARY 52 POSITIONEN.belegnr 1 Using where |
AW: Doppel-Select-Anweisung zu langsam
Zitat:
Code:
Zumindest auf meiner Testdatenbank mit ca. 1000000 Datensätzen mit ähnlicher Datenstruktur, wird die eigentlich Abfrage dann in unter einer Sekunde abgearbeitet.
/* Index über SpalteDatum erforderlich */
CREATE VIEW V_SpalteA2012( SpalteA) AS Select distinct SpalteA from Tabelle1 where SpalteDatum between '20120101' and '20121231'; |
AW: Doppel-Select-Anweisung zu langsam
Ich glaub ich muss mir unbedingt mal bissi Literatur zur MySQL-Optimierung besorgen.
|
AW: Doppel-Select-Anweisung zu langsam
Hallo Zusammen,
habe mich von meinem Herzanfall erholt ;-) Ok, Spaß beiseite, ich war gestern geschäftlich unterwegs und konnte mich daher nicht weiter dem Problem wittmen. Ich hatte nicht erwartet, so eine Diskussion loszutreten... Ich habe sie gelesen und das, was ich verstanden habe, auch ausprobiert, aber ohne Erfolg. Selbst nach einer Stunde bekomme ich noch kein Ergebnis...wollte einfach mal wissen, was passiert, wenn ich warte... Ich überlege jetzt einen anderen Ansatz: Für mich ist es nur wichtig, dass ich alle Arbeitsgänge eines Auftrags ausgegeben bekomme. Daher kann ich also auch damit leben, dass ich nur die Aufträge mit allen Arbeitsgängen erhalte, die in dem entsprechenden Zeitraum gestartet und auch beendet wurden. Hier mal ein Beispiel Auftrag...AG...Rückmeldung Diesen Auftrag möchte ich komplett mit allen Arbeitsgängen bekommen 0004711...10...20120105 0004711...20...20120115 0004711...30...20120117 0004711...40...20120123 0004711...50...20120205 Diesen Auftrag will ich komplett mit allen Arbeitsgängen NICHT bekommen, weil der AG 10 in 2011 fertig war 0006874...10...20111231 0006874...20...20120103 0006874...30...20120103 0006874...40...20120103 0006874...50...20120103 Diesen Auftrag will ich komplett mit allen Arbeitsgängen NICHT bekommen, weil der AG 50 in 2013 fertig war 0009632...10...20121205 0009632...20...20121217 0009632...30...20121220 0009632...40...20121228 0009632...50...20130110 Kann mir jemand bei der SQL-Anweisung helfen? Vielen Dank Patrick |
AW: Doppel-Select-Anweisung zu langsam
Also Du hast tatsächlich eines der hier genannten Statements inkl Distinct ausgeführt?
Zeig doch mal bitte und den Ausführungsplan dazu auch! |
AW: Doppel-Select-Anweisung zu langsam
Hallo Jobo,
folgende SQL-Anweisung war nach über einer Stunde noch nicht fertig:
Delphi-Quellcode:
Ich bin nicht der fitteste in SQL. Wenn ich da etwas falsch umgesetzt habe, bin ich um jede Hilfe froh.
select
concat(A.WAAUNR, A.WAAUPO), A.WATENR, A.WAGFMG, A.OAAGBZ, A.OAMANR, DATE_FORMAT(A.OARMDA,"%d.%m.%Y") AS OARMDA, A.OARMMG from as400archiev A ,(select DISTINCT WAAUNR, WAAUPO, OARMDA from as400archiev where OARMDA between '20120101' and '20121231') B where A.WAAUNR=B.WAAUNR and A.WAAUPO=B.WAAUPO Vielen Dank Patrick |
AW: Doppel-Select-Anweisung zu langsam
wofür brauchst Du das OARMDA im subselect?
|
AW: Doppel-Select-Anweisung zu langsam
Stimmt, das hatte ich in einer der vielen Versuche mal mit reingenommen...
Aber an der Geschwindigkeit hat sich nichts geändert... Ich fürchte, so komme ich nicht weiter :cry: |
AW: Doppel-Select-Anweisung zu langsam
Was ist mit Indizes und Ausführungsplänen?
Wieviel DS ergibt das Subselect? Lass Dir doch nicht alles aus der Nase ziehen, hier kann keiner zaubern. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:14 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz