AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken SQL Script optimieren damit es schneller geht
Thema durchsuchen
Ansicht
Themen-Optionen

SQL Script optimieren damit es schneller geht

Ein Thema von Dumpfbacke · begonnen am 24. Feb 2017 · letzter Beitrag vom 25. Feb 2017
Antwort Antwort
Seite 2 von 3     12 3      
Dumpfbacke

Registriert seit: 10. Mär 2005
Ort: Mitten in Deutschland
329 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#11

AW: SQL Script optimieren damit es schneller geht

  Alt 25. Feb 2017, 08:18
Hallo,
was passiert, wenn Du die letzten beiden where's weglässt?

<>"N" hattest du ja selber schon ausgeschlossen.
Das Storno kannst Du selber im Code prüfen.
Das geht auch nicht schneller. Ich habe esnur beutzt, um den Anzahl der Datensätze zu veringern.
Tanja
  Mit Zitat antworten Zitat
Dumpfbacke

Registriert seit: 10. Mär 2005
Ort: Mitten in Deutschland
329 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#12

AW: SQL Script optimieren damit es schneller geht

  Alt 25. Feb 2017, 08:32
Ich zeige Euch mal wie die Daten in den Tabellen aussehen können. Eventuell wird es dann deutlicher wo mein Fehler leigt.

Also als erstes einmal bei dem Status N kann es keine Zeile in Tabelle2 geben. Es kann auch keine Zeile in Tabelle 2 geben bei dem der Wert des Feldes Status NULL ist.

Es liegt ein Index auf den Felder CoNummer und Status der Teabelle1 sowie CoNummer und Status der Tabelle2


Delphi-Quellcode:
Tabelle1
Masternummer CoNummer Status
1 2514 N
2 2515 Start
3 2516 Warten
4 2517 Produktion
5 2518 Ausgabe
6 2519 Komplett



Tabelle2
CoNummer Status
2515 Start
2516 Start
2517 Start
2517 Warten
2518 Start
2518 Warten
2518 Produktion
2518 Ausgabe
Als Ergebnis möchte ich nun haben 1,3,4 und 6. Also alle Datensätze aus Tabelle1 wo kein Datensatz in Tabelle 2 vorhanden ist.
Tanja

Geändert von Dumpfbacke (25. Feb 2017 um 08:39 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von dataspider
dataspider

Registriert seit: 9. Nov 2003
Ort: 04539 Groitzsch
1.350 Beiträge
 
Delphi 11 Alexandria
 
#13

AW: SQL Script optimieren damit es schneller geht

  Alt 25. Feb 2017, 09:19
IMHO ist hier nicht viel zu machen.
Für die Verknüpfung mit Tabelle 2 hilft dir kein Index.
Fakt ist:
Die Indexe greifen nur auf Status und Storno, alle anderen Datensätze von Tabelle 1 werden beim Select "angefasst".
Du kannst nur noch sicherstellen, das zur Prüfung auch nur ein Datensatz in Tabelle 2 "angefasst" wird,
indem du statt einem Join exists verwendest.

Wenn es schnell sein soll, benötigst du IMHO ein zusätzliches indexiertes Feld in Tabelle 1,
welches über "after insert update delete" Trigger der Tabelle 2 aktuell gehalten wird.

Frank
Frank Reim

Geändert von dataspider (25. Feb 2017 um 09:23 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Valle
Valle

Registriert seit: 26. Dez 2005
Ort: Karlsruhe
1.223 Beiträge
 
#14

AW: SQL Script optimieren damit es schneller geht

  Alt 25. Feb 2017, 09:44
Ich bin neugierig, aber leider erfahrungslos mit Firebird. Im Prinzip würde das hier das Ergebnis liefern, oder?

Code:
SELECT * FROM Tabelle1
WHERE NOT EXISTS (
    SELECT CoNummer FROM Tabelle2 WHERE Tabelle2.CoNummer = Tabelle1.CoNummer
)
Valentin Voigt
BOFH excuse #423: „It's not RFC-822 compliant.“
Mein total langweiliger Blog
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#15

AW: SQL Script optimieren damit es schneller geht

  Alt 25. Feb 2017, 10:44
Ich bin neugierig, aber leider erfahrungslos mit Firebird. Im Prinzip würde das hier das Ergebnis liefern, oder?

Code:
SELECT * FROM Tabelle1
WHERE NOT EXISTS (
    SELECT CoNummer FROM Tabelle2 WHERE Tabelle2.CoNummer = Tabelle1.CoNummer
)
Das war beim Lesen der Anforderungen jetzt auch gerade mein erster Gedanke.

Will ich nur wissen, ob es etwas gibt oder nicht, dann frage ich mit Exists ab:
Beispiele:
SQL-Code:
/* gibt es da was in Tabelle2 zu Tabelle1? */
select benötigtespalte(n) from tabelle1
where exists (select 1 from tabelle2 where tabelle1.schlüssel = tabelle2.schlüssel)

/* gibt es nichts in Tabelle 2 zu Tabelle 1? */
select benötigtespalte(n) from tabelle1
where not exists (select 1 from tabelle2 where tabelle1.schlüssel = tabelle2.schlüssel)
Das war nach meiner bisherigen Erfahrung immer die schnellste Variante für eine Existenz- bzw. Nichtexistenzprüfung.

Brauche ich sowas nur für kleine Teilmengen der betroffenen Tabellen dann wird daraus sinngemäß:
SQL-Code:
select * from (
  select benötigtespalte(n) from tabelle1
  where EinschränkendeBedingungen zu Tabelle1
) a
where exists /* Wenns was geben soll */
(
  select Schlüsselspalten from
  (
    select Schlüsselspalten from tabelle2
    where EinschränkendeBedingungen zu Tabelle2
  ) b
)
where a.schlüssel = b.schlüssel
Ja, ich weiß, das wird zuweilen sehr schwer lesbar, aber wenn's hilft, dann ist dem so. Im Zweifelsfalle erstellt man sich für die "innern Selects" halt Views, dann ist der Zugriff wieder wie im ersten Beispiel leicht lesbar, ohne das Laufzeitveränderungen auftreten.

Zitat von hoika2:
Genau das macht der Query-Optimizer ja schon selbst (eigentlich ...)
Syntaktisch mag das zutreffen.

Meine Erfahrung hat mich jedoch gelehrt, dass der Optimizer hier bei starken Einschränkungen der Daten auf Teilmengen, die dann zu verknüpfen sind, häufig "daneben liegt".
Er kann bei der Optimierung (vermutlich) die aus den Einschränkungen resultierenden Teilmengen nicht optimal einschätzen, um den laufzeittechnisch und dateninduziert optimalen Plan zu erstellen.

Würde dashier (sinngemäß) den Anforderungen entsprechen?
SQL-Code:
select a.Masternummer from
(
  select Masternummer from tabelle1
  where status <> 'Nand status is not null
) a
where not exists (
  select 1 from tabelle2 b
  where a.CoNummer = b.CoNummer
)
Und ist es auch akzeptabel schnell?
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#16

AW: SQL Script optimieren damit es schneller geht

  Alt 25. Feb 2017, 10:54
Das war nach meiner bisherigen Erfahrung immer die schnellste Variante für eine Existenz- bzw. Nichtexistenzprüfung.
Ist leider nicht allgemeingültig!
SQL-Code:
select *
from t1 left join t2 on (t1.id=t2id)
where t2.id is null
Ist meist etwas schneller, kommt aber wohl vor allem auf die konkreten Daten (und die DB) an.
Man sollte immer beide Wege probieren.

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#17

AW: SQL Script optimieren damit es schneller geht

  Alt 25. Feb 2017, 11:08
Ist leider nicht allgemeingültig!
Das Schlimme daran ist ja, dass es ja nicht nur bei unterschiedlichen Datenbankherstellern unterschiedlich ist, sondern je nach Datenbank eines Herstellers datenabhängig nicht zwingend den "richtigen" Weg gibt, sondern auch noch abhängig von der darunterliegenden Hardware (z. B. identische Maschinen mit lediglich unterschiedlicher Speicherbestückung) durchaus unterschiedliche Verhaltensweisen geben kann.

Im Zweifel gilt bei mir immer:

Ausprobieren, bis die (hoffentlich) beste Lösung gefunden wurde.

"Die beste Lösung" gibt es nicht.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: SQL Script optimieren damit es schneller geht

  Alt 25. Feb 2017, 11:36
In Firebird kann man sich doch bestimmt auch den EXPLAIN PLAN/ANALYSE ausgeben lassen und sieht ob und welcher Index verwendet wird.

Mal probiert den JOIN umzudrehen?
Im Beispiel hat Tabelle2 mehr Einträge.
FROM Tabelle1 JOIN Tabelle2 > für jeden Eintrag in Tabelle 1 alle vielen Einträge in Tabelle 2 durchsuchen (NULL steht nicht im Index, also FullScan und Index ignoriert)
FROM Tabelle2 JOIN Tabelle1 > für jeden Eintrag in Tabelle 2 die wenigen Einträge in Tabelle 2 durchsuchen

Oder halt die Variante ohne JOIN.
SQL-Code:
SELECT *
FROM Tabelle1
WHERE NOT exists(
  SELECT true
  FROM Tabelle2
  WHERE Tabelle1.CoNummer = Tabelle2.CoNummer
    AND Tabelle1.Status = Tabelle2.Status
  LIMIT 1
)
Das SubSelect kann nun einen Index gut ausnutzen, wenn der über CoNummer+Status geht.
Keine Ahnung, ob EXISTS schon so schlau ist und die Felder (hier nur ein True) ignoriert, weil sie niemals genutzt werden,
und bereits ein LIMIT verwendet, da ja schon ab dem ersten Fund das Ergebnis feststeht.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (25. Feb 2017 um 11:39 Uhr)
  Mit Zitat antworten Zitat
Dumpfbacke

Registriert seit: 10. Mär 2005
Ort: Mitten in Deutschland
329 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#19

AW: SQL Script optimieren damit es schneller geht

  Alt 25. Feb 2017, 11:53
In Firebird kann man sich doch bestimmt auch den EXPLAIN PLAN/ANALYSE ausgeben lassen und sieht ob und welcher Index verwendet wird.



Oder halt die Variante ohne JOIN.
SQL-Code:
SELECT *
FROM Tabelle1
WHERE NOT exists(
  SELECT true
  FROM Tabelle2
  WHERE Tabelle1.CoNummer = Tabelle2.CoNummer
    AND Tabelle1.Status = Tabelle2.Status
  LIMIT 1
)
Firebird kennt kein true und auch kein LIMIT 1
Tanja

Geändert von Dumpfbacke (25. Feb 2017 um 12:04 Uhr)
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#20

AW: SQL Script optimieren damit es schneller geht

  Alt 25. Feb 2017, 12:09
Würde das in etwa so übersetzen:

Statt
SQL-Code:
SELECT *
FROM Tabelle1
WHERE NOT exists(
  SELECT true
  FROM Tabelle2
  WHERE Tabelle1.CoNummer = Tabelle2.CoNummer
    AND Tabelle1.Status = Tabelle2.Status
  LIMIT 1
)
könnte dashier gehen:
SQL-Code:
SELECT *
FROM Tabelle1
WHERE NOT exists(
  SELECT first 1 1
  FROM Tabelle2
  WHERE Tabelle1.CoNummer = Tabelle2.CoNummer
    AND Tabelle1.Status = Tabelle2.Status
)
Syntaktisch geht das so unter FireBird (grade mal ausprobiert), ob's auch sinnvolle Ergebnisse liefert, kann ich nicht sagen, first 1 1 sieht jedenfalls seltsam aus
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


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 01:41 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