AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

SQL Nachhilfe

Ein Thema von HCB · begonnen am 27. Jan 2024 · letzter Beitrag vom 1. Feb 2024
Antwort Antwort
Seite 1 von 2  1 2      
HCB

Registriert seit: 12. Feb 2020
172 Beiträge
 
Delphi 12 Athens
 
#1

SQL Nachhilfe

  Alt 27. Jan 2024, 09:47
Datenbank: Access • Version: 2003 • Zugriff über: FireDac
Hallo liebe SQL-Experten,
ich bin hier am Optimieren meiner SQL Queries. Folgende Abfrage funktioniert wie es sein soll, jedoch ist diese mit ca. 5 sek. etwas zu langsam. Da kann man sicher noch was rausholen:

Delphi-Quellcode:
SELECT s.ArtNr, s.ArtName1,s.ArtGruppe, s.ArtZusInfo4
FROM sArtikel s
WHERE NOT EXISTS (SELECT *
                   FROM ArtLief l
                   WHERE s.ArtNr = l.ArtLiefArtNr
                   and l.ArtLiefLiefNr = s.ArtZusInfo4
                   )
and s.ArtInaktiv = false
and s.ArtZusInfo4 like 'K*'
order by s.ArtNr;
Es wäre sehr nett, wenn mir wieder jemand helfen könnte.

LG Harry
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.586 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: SQL Nachhilfe

  Alt 27. Jan 2024, 10:00
Auf den ersten Blick würde ich vermuten, dass ein left join mit Abfrage, ob das gejointe Feld null ist, schneller ist.

Denn so muss ja für jeden Datensatz eine Abfrage über die ganze Tabelle laufen. Wenn dann die dabei abgefragten Felder nicht in einem Index sind, ist das noch einmal langsamer.

Indizes sind aber auch generell ein Thema, um Abfragen zu beschleunigen.

Hast du dir zu der Abfrage einmal den Ausführungsplan angeschaut? Der zeigt, wo wieviel Zeit verbraucht wird.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.071 Beiträge
 
Delphi 12 Athens
 
#3

AW: SQL Nachhilfe

  Alt 27. Jan 2024, 10:11
Jupp, ein JOIN, anstatt des SubSELECTs.
Und dann auch schauen, ob auf den verlinkten Feldern ein Index liegt.

SQL-Code:
SELECT s.ArtNr, s.ArtName1,s.ArtGruppe, s.ArtZusInfo4
FROM sArtikel AS s
LEFT JOIN ArtLief AS l
   ON l.ArtLiefArtNr = s.ArtNr
  AND l.ArtLiefLiefNr = s.ArtZusInfo4
WHERE s.ArtInaktiv = false
  AND s.ArtZusInfo4 LIKE 'K*'
  AND l.irgendwas IS NULL -- hier irgendein NOT NULL Keyfield, vielleicht l.ArtLiefArtNr
INDIZE auf:
l) ArtLiefLiefNr, ArtLiefArtNr (hier dachte ich erst es wäre zwei mal das gleiche, aber einfach das = umgedreht und schon fällt es sofort auf)
s) ArtInaktiv, ArtZusInfo4, ArtNr

Und bezüglich des LIKE, k.A. wie es bei Access aussieht, aber z.B. in MySQL gibt es verschiedene Indize, wobei Manche für sowas wie LIKE nicht geeignet sind.
Zum Glück ist auch der * am Ende, denn die meisten Indize sind für Suchen, wo * am Anfang oder mittendrin wäre, ebenfalls ungeeignet.

Gut, das System könnte natürlich auch intelligenter sein und erkennen, dass das Subselect als JOIN besser geeignet ist und es das entsprechend selbstständig umstellt.
* anstatt für jede Zeile eine einzelne Abfrage auszufühen
* die Tabelle nur einmal lagen und jeweils nur schnell darin zu suchen

Wenn die Optimierung im DSMS nichts kann, sie also nicht erkennen würde, dass dein Subsselekt langsam ist und es scheller wäre die folgenden AND vorzuziehen,
dann würde das Subselect für JEDEN Datensatz ausgewertet, anstatt nur für einen Teil, nach der Filterung durch die beiden = , also
SQL-Code:
WHERE s.ArtInaktiv = false
  AND s.ArtZusInfo4 like 'K*'
  AMD NOT EXISTS (SELECT *
                    FROM ArtLief l
                    WHERE s.ArtNr = l.ArtLiefArtNr
                    and l.ArtLiefLiefNr = s.ArtZusInfo4
                 )
Drum kommt bei mir gedanklich auch das IS NULL "gedanklich" als letztes im WHERE vor ,
wobei ein NULL-Prüfung in einem INDEX wohl auch wiederum optimaler/schneller sein dürfte, als ein = oder LIKE.


PS: In vielen DBMS gibt SQL-Befehle oder Zusatztools, um das Statement analysieren zu lassen.
Was wird wo gemacht (z.B. FullTableScann anstatt IndexScan) und vielleicht auch vie viel Zeit welcher Teil braucht.

sowas hab ich jetzt noch nicht gesehn,
https://www.postgresql.org/docs/curr...l-analyze.html
https://docs.oracle.com/en/database/...F-DCB3772C1B0E
aber
https://support.microsoft.com/en-us/...b-30b86082d792
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (27. Jan 2024 um 10:28 Uhr)
  Mit Zitat antworten Zitat
HCB

Registriert seit: 12. Feb 2020
172 Beiträge
 
Delphi 12 Athens
 
#4

AW: SQL Nachhilfe

  Alt 27. Jan 2024, 10:40
Vielen lieben Dank für Euere schnell Hilfe.
Himitsus erster SQL Code hat perfekt gepasst! Ausführungszeit jetzt 0.03 sek. Brutal geil!
Jetzt läufts super schnell mit diesem Code:
Delphi-Quellcode:
SELECT s.ArtNr, s.ArtName1,s.ArtGruppe, s.ArtZusInfo4
FROM sArtikel AS s
LEFT JOIN ArtLief AS l
   ON l.ArtLiefArtNr = s.ArtNr
  AND l.ArtLiefLiefNr = s.ArtZusInfo4
WHERE s.ArtInaktiv = false
  AND s.ArtZusInfo4 LIKE 'K*'
  AND l.ArtLiefArtNr IS NULL
order by s.ArtNr;
  Mit Zitat antworten Zitat
HCB

Registriert seit: 12. Feb 2020
172 Beiträge
 
Delphi 12 Athens
 
#5

AW: SQL Nachhilfe

  Alt 31. Jan 2024, 15:22
Da ist mir doch noch einer auffällig langsam:
Delphi-Quellcode:
SELECT
A.ABFDocErfNr,A.ABFDocDatum,A.ABFDocKundenNr, A.ABFDocKundekurzbez,
P.ABFPosArtNr,P.ABFPosName1,P.ABFPosEPreis,
M.PersKtoPreisGruppe
FROM (ABFDok as A
INNER JOIN ABFPos as P ON A.ABFDocId = P.ABFPosDocID )
inner join sPersKto as M on M.PersKtoNummer = A.ABFDocKundenNr
where P.ABFPosArtNr = '11024060and Year([A.ABFDocDatum]) > Year(Date())-5 and A.ABFDocType = 1
ORDER BY A.ABFDocId desc;
Diesesmal scheint mir (als Dilli) das etwas komplizierter wegen den 2 inner joints.
Könnte nochmals Hilfe gebrauchen um die Query flinker zu machen.

LG Harry
  Mit Zitat antworten Zitat
Benutzerbild von Jasocul
Jasocul

Registriert seit: 22. Sep 2004
Ort: Delmenhorst
1.354 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: SQL Nachhilfe

  Alt 31. Jan 2024, 16:02
... inner joints.
Harry, YMMD

Was mir sofort auffällt:
Durch
Code:
Year([A.ABFDocDatum]) > Year(Date())-5
kann für "ABFDocDatum" schonmal kein Index mehr gezogen werden.
Dann teste bitte zusätzlich noch, ob es ohne
Code:
order by
spürbar schneller ist.

Leider kann ich heute nicht mehr weiterhelfen, da ich gleich auf einer Demo bin.
Peter
  Mit Zitat antworten Zitat
fisipjm

Registriert seit: 28. Okt 2013
299 Beiträge
 
#7

AW: SQL Nachhilfe

  Alt 31. Jan 2024, 16:29
Ich würd jetzt einfach mal das probieren:

Code:
-- Index für ABFPos
CREATE INDEX idx_ABFPos_ABFPosDocID ON ABFPos (ABFPosDocID);

-- Index für sPersKto
CREATE INDEX idx_sPersKto_PersKtoNummer ON sPersKto (PersKtoNummer);

-- Index für ABFDok
CREATE INDEX idx_ABFDok_ABFPosArtNr_Datum_Type_KundenNr ON ABFDok (ABFPosArtNr, ABFDocDatum, ABFDocType, ABFDocKundenNr);
  Mit Zitat antworten Zitat
HCB

Registriert seit: 12. Feb 2020
172 Beiträge
 
Delphi 12 Athens
 
#8

AW: SQL Nachhilfe

  Alt 31. Jan 2024, 18:29
Hallo,
mit den indexen wurde es keider auch nicht schneller.

LG Harry
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.736 Beiträge
 
Delphi 6 Enterprise
 
#9

AW: SQL Nachhilfe

  Alt 31. Jan 2024, 18:40
Year([A.ABFDocDatum]) > Year(Date())-5

Könnte man vllt. umformulieren zu

[A.ABFDocDatum] >= DateSerial(Year(Date())-4, 1, 1 )
Ralph
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.071 Beiträge
 
Delphi 12 Athens
 
#10

AW: SQL Nachhilfe

  Alt 31. Jan 2024, 19:32
Jupp, da hier das Feld durch eine Funktion geht, kann nicht der Index genutzt werden, welcher auf diesem Feld liegt.

Also direkt das Feld direkt verwenden, damit der Index genutzt werden kann, wäre somit eine Lösung (siehe Jumpy)



Oder einen Index auf das Jahr erstellen, also auf Year([A.ABFDocDatum]) .

Weiß aber nicht, ob es sowas auch im Access gibt.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (31. Jan 2024 um 19:38 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:06 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz