AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Firebird IN, EXISTS Langsam
Thema durchsuchen
Ansicht
Themen-Optionen

Firebird IN, EXISTS Langsam

Ein Thema von Gruber_Hans_12345 · begonnen am 7. Feb 2011 · letzter Beitrag vom 8. Feb 2011
Antwort Antwort
Gruber_Hans_12345

Registriert seit: 14. Aug 2004
1.441 Beiträge
 
Delphi 2007 Professional
 
#1

AW: Firebird IN, EXISTS Langsam

  Alt 7. Feb 2011, 18:48
ein weiteres Statement, daß Du mal austesten könntest:

Code:
SELECT A.ID
  FROM ARTIKEL A
  LEFT JOIN V_AUFTRAG_PO T ON (A.ID = T.ARTIKEL_ID)
  WHERE T.ARTIKEL_ID IS NULL
  GROUP BY A.ID
Sonderlich performant sind solche Abfragen leider meist nicht. Zu dem obigen Statement sollten Indizes auf ARTIKEL.ID und V_AUFTRAG_PO.ARTIKEL_ID liegen.

Gruß aus dem hohen Norden
Also Indexe liegt auf A.ID (primär Index)
DAs mit dem zusätzlichen Index werde ich morgen gelich mal probieren, obs wirklich vielleicht nur daran lag ...

Das mit dem Left OUTER JOIN geht zwar ein bisschen schneller aber auch nicht viel
Das problem ist das in der realen Anwendung die zugelinkte Tabelle noch 2 weitere benötigt, dann wird es mit dem JOIN auch wieder sehr komplex

Im Moment habe ich nur noch die idee eventuell die aktuellen werte obs einträge in den V_AUFTRAG_PO gibt oder nicht in eine temporäre Tabelle oder irgendwie anders zu machen ....
Gruss Hans

2B or not 2B, that is FF
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#2

AW: Firebird IN, EXISTS Langsam

  Alt 7. Feb 2011, 19:57
@mkinzler
Die Beschreibung klingt gut
Für einen einzelnen Datensatz ist es ja sicherlich auch richtig.
Aber was macht der Optimizer, wenn das not exists gegen tausende oder mehr Artikel gefahren wird? Immer wieder los rennen und suchen .. ?

@Gruber_Hans_12345
1500 -2000 Datensätze sind nicht viel.
Wenn das V_AUFTRAG_PO im echten Leben so komplex ist, lohnt es sich vielleicht, erst die Differenz zu bilden (die mglw. noch zu viele Datensätze enthält) und anschließend auf dem Ergebnis die "komplexen " Joins zu fahren.

Also ungefähr
Code:
select * from (
  SELECT A.ID
  FROM ARTIKEL A
  LEFT JOIN POSITION T ON (A.ID = T.ARTIKEL_ID)
  WHERE T.ARTIKEL_ID IS NULL
  GROUP BY A.ID
  ) Dif
where .. komplexe Bedingungen
Hier gibts vielleicht noch tolle Hinweise zum Optimizer.
Gruß, Jo
  Mit Zitat antworten Zitat
Gruber_Hans_12345

Registriert seit: 14. Aug 2004
1.441 Beiträge
 
Delphi 2007 Professional
 
#3

AW: Firebird IN, EXISTS Langsam

  Alt 7. Feb 2011, 20:55
@mkinzler
Die Beschreibung klingt gut
Für einen einzelnen Datensatz ist es ja sicherlich auch richtig.
Aber was macht der Optimizer, wenn das not exists gegen tausende oder mehr Artikel gefahren wird? Immer wieder los rennen und suchen .. ?
Also von denzeiten her, würde ich sagen, ja er macht das - leider - das ist ja das problem hier

@Gruber_Hans_12345
1500 -2000 Datensätze sind nicht viel.
Wenn das V_AUFTRAG_PO im echten Leben so komplex ist, lohnt es sich vielleicht, erst die Differenz zu bilden (die mglw. noch zu viele Datensätze enthält) und anschließend auf dem Ergebnis die "komplexen " Joins zu fahren.

Also ungefähr
Code:
select * from (
  SELECT A.ID
  FROM ARTIKEL A
  LEFT JOIN POSITION T ON (A.ID = T.ARTIKEL_ID)
  WHERE T.ARTIKEL_ID IS NULL
  GROUP BY A.ID
  ) Dif
where .. komplexe Bedingungen
Hier gibts vielleicht noch tolle Hinweise zum Optimizer.
Also das mit dem group habe ich auch schon probiert, das hat leider auch gar nichts gebracht, entweder hilft dann hier der index soviel, das es nicht mehr soviel unterschied macht,
Hätte es auch schon als STORED PRCOEDURE probiert, aber noch gescheitert

Als reines Script im Client abgelegt, zuerst alle ARTIKEL IDs laden, dann die Liste mit den verwendeten laden, davon per Delphi ein DIFF machen, und dann noch mal ein SELECT -> ist um welten schneller, aber leider zu komples, für viele sachen
Gruss Hans

2B or not 2B, that is FF
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#4

AW: Firebird IN, EXISTS Langsam

  Alt 7. Feb 2011, 21:24
Ich glaub, Du hast mich falsch verstanden. Es ging mir nicht ums Group, das innere Statement ist ja nur eine Kopie des von mir favorisierten Statement von TBx. Ich hab lediglich das "V_AUFTRAG_PO" gegen "POSITION" getauscht, um zu verdeutlichen, dass Du den komplexen View erstmal beiseite lässt.

Hast Du Dir mal den Optimizer Link angeschaut?
Gruß, Jo
  Mit Zitat antworten Zitat
Gruber_Hans_12345

Registriert seit: 14. Aug 2004
1.441 Beiträge
 
Delphi 2007 Professional
 
#5

AW: Firebird IN, EXISTS Langsam

  Alt 7. Feb 2011, 21:43
Ich glaub, Du hast mich falsch verstanden. Es ging mir nicht ums Group, das innere Statement ist ja nur eine Kopie des von mir favorisierten Statement von TBx. Ich hab lediglich das "V_AUFTRAG_PO" gegen "POSITION" getauscht, um zu verdeutlichen, dass Du den komplexen View erstmal beiseite lässt.

Hast Du Dir mal den Optimizer Link angeschaut?
JA, das problem ist die komplexe Abfrage mit 3 Tabellen per Joins ist in der inneren SQL - Also dort wo geschaut wird, ob diese Artikel in der Positions Tabelle verhanden sind (Verlinkt mit Auftrag Tabelle und einer Auftrags informations Tabelle) deshalb ist es da problematisch ...

... habs zwar gelesen, aber hab mir nicht wirklich was raussuchen können, was mir helfen könnte in diesem fall


Ich habe einfach das problem, das so eine "primitive" sache, wo es eigentlich nur darum geht eine SELECT zu machen (die 0.05 sekunden dauert) und von dieser dann ID's aus einer anderen Abfrage abzuziehen (die auch 0.05 sekunden dauert) - das dann 26 sekunden dauert ... das geht enfach nicht in meinen kopf, das man das nicht mit "normalen einfachen" SQL Mitteln zumindest auf 0.5 Sekudnen oder so optimieren kann
Und das müsste ja eigentlich auch OHNE einen Index auf Artikel_ID funktionieren ... (Schon klar ich werde morgen den Index drauf legen ... aber ist mir noch immer nicht ganz logisch, das es nicht ohne den geht ... )
Gruss Hans

2B or not 2B, that is FF
  Mit Zitat antworten Zitat
omata

Registriert seit: 26. Aug 2004
Ort: Nebel auf Amrum
3.154 Beiträge
 
Delphi 7 Enterprise
 
#6

AW: Firebird IN, EXISTS Langsam

  Alt 7. Feb 2011, 22:14
Deine DB-Struktur sieht also folgendermaßen aus...
SQL-Code:
CREATE TABLE artikel (
  artikel_id int,
  CONSTRAINT PK_artikel
    PRIMARY KEY (artikel_id)
);

CREATE TABLE position (
  position_id int,
  CONSTRAINT PK_position
    PRIMARY KEY (position_id)
);

CREATE TABLE artikel_position (
  artikel_id int,
  position_id int,
  CONSTRAINT PK_artikel_position
    PRIMARY KEY (artikel_id, position_id),
  CONSTRAINT FK_artikel_position_artikel
    FOREIGN KEY (artikel_id) REFERENCES artikel (artikel_id),
  CONSTRAINT FK_artikel_position_position
    FOREIGN KEY (position_id) REFERENCES position (position_id)
);
Ist das richtig?

Geändert von omata ( 7. Feb 2011 um 22:21 Uhr)
  Mit Zitat antworten Zitat
Gruber_Hans_12345

Registriert seit: 14. Aug 2004
1.441 Beiträge
 
Delphi 2007 Professional
 
#7

AW: Firebird IN, EXISTS Langsam

  Alt 8. Feb 2011, 08:06
Also das ist die original Abfrage
Code:
SELECT A.ARTIKELNUMMER
FROM ARTIKEL A
/*Hier wäre noch joins drinnen, aber die habe ich mal weggelassen, da diese keine zeit in anspruch nehmen */
WHERE A.ID NOT IN
(
SELECT T.ARTIKEL_ID
FROM AUFTRAG VA, AUFTRAG_INFO AF, POSITIONEN T
WHERE (AF.ID = VA.INFO_ID) AND (T.AUFTRAG_ID = VA.ID) AND (VA.MesseSTATUS > 0)
AND ((CAST(AF.MesseBis AS Date) >= CURRENT_TIMESTAMP) And (Cast(AF.MesseVon AS Date) <= CURRENT_TIMESTAMP + 10))
)

[EDIT}Also das erzeugen eines Index auf POSITIONEN(ARTIKEL_ID) hat es gebracht ... nun dauerrts ca 0.05 sekunden ... ich verstehe zwar nicht warum er das braucht aber, vielleicht merke ich es mir nun .... [/EDIT]
Gruss Hans

2B or not 2B, that is FF
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 15. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#8

AW: Firebird IN, EXISTS Langsam

  Alt 7. Feb 2011, 21:35
Wenn wir mal folgende Abfrage anschauen:
SELECT A.ID FROM ARTIKEL A WHERE NOT EXISTS (SELECT * FROM V_AUFTRAG_PO T WHERE T.ARTIKEL_ID = A.ID)
dann kann diese Abfrage "rasend schnell" ablaufen, wenn auf dem Feld V_AUFTRAG_PO.ARTIKEL_ID ein Index existiert.
Die SQL-Engine sollte in diesem Fall nur den Index der Tabelle V_AUFTRAG_PO befragen ob ein bestimmter Schlüssel vorhanden ist oder nicht.
Die Unterabfrage SELECT * FROM V_AUFTRAG_PO wird dabei im Grunde genommen überhaupt nicht ausgeführt.
Dafür ist es natürlich erforderlich, dass Firebird so schlau ist nur den Index abzurufen und Zugriffe auf die Tabelle V_AUFTRAG_PO zu unterlassen.
Manchmal (je nach DBMS) erkennt die Engine diese Abkürzung nur wenn in der Unterabfrage SELECT * FROM ... steht.
Im Prinzip kann man in der Unterabfrage auch SELECT V_AUFTRAG_PO.ARTIKEL_ID FROM V_AUFTRAG_PO schreiben; das Ergebnis ist theoretisch gleichwertig zu SELECT * FROM V_AUFTRAG_PO.

Irgendwie stösst SQL hier an seine Grenzen, weil man in der Unterabfrage eine Feldliste angeben muss, die doch im Zusammenhang mit EXISTS nie benützt wird.

Geändert von sx2008 ( 7. Feb 2011 um 21:42 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


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 18:55 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