AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Firebird - where Bedingung mit Bedingung
Thema durchsuchen
Ansicht
Themen-Optionen

Firebird - where Bedingung mit Bedingung

Ein Thema von lxo · begonnen am 3. Sep 2024 · letzter Beitrag vom 4. Sep 2024
Antwort Antwort
Seite 1 von 2  1 2      
lxo

Registriert seit: 30. Nov 2017
288 Beiträge
 
Delphi 12 Athens
 
#1

Firebird - where Bedingung mit Bedingung

  Alt 3. Sep 2024, 08:20
Datenbank: Firebird • Version: 5 • Zugriff über: -
Hallo,

ich habe einen Fall den ich nicht ganz verstehe und hoffe es gibt da eine Lösung zu.
In einer where-Bedingung möchte ich anhand eines Booleans entscheiden welche Bedingung genutzt werden soll.

Code:

-- 314 indizierte reads auf die Tabelle
T.ID = 1

-- 290 indizierte reads auf die Tabelle
T.ID= 20

-- 604 indizierte reads auf die Tabelle
            ( ( TRUE and
              ( T.ID = 1)) or
              ( not TRUE and
              ( T.ID= 20)))
Warum macht Firebird bei der verschachtelten Bedingung 604 reads und nicht 314?
Kann ich das evtl. mit einem vorgegebenen PLAN beeinflussen?
Hab ich probiert aber nicht hinbekommen mit dem PLAN bisher.
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.464 Beiträge
 
Delphi 12 Athens
 
#2

AW: Firebird - where Bedingung mit Bedingung

  Alt 3. Sep 2024, 15:59
Code:
select * from tabelle where ((:condition and (id = 1)) or (not :condition and (id = 20))
Der Plan wird aufgestellt, bevor dein Parameter zugewiesen wird (True, False, NULL).
So, als wenn da zwei unterschiedliche Parameter sind und deshalb beide Teilbedingungen wahr sein könnten.

Code:
select * from tabelle where id = iif(:condition, 1, 20)

Geändert von Blup ( 3. Sep 2024 um 16:01 Uhr)
  Mit Zitat antworten Zitat
lxo

Registriert seit: 30. Nov 2017
288 Beiträge
 
Delphi 12 Athens
 
#3

AW: Firebird - where Bedingung mit Bedingung

  Alt 3. Sep 2024, 16:01
Code:
select * from tabelle where id = ((:condition and (id = 1)) or (not :condition and (id = 20))
Der Plan wird aufgestellt, bevor dein Parameter zugewiesen wird (True, False, NULL).
So, als wenn da zwei unterschiedliche Parameter sind und deshalb beide Teilbedingungen wahr sein könnten.

Code:
select * from tabelle where id = iif(:condition, 1, 20)
Ja sowas habe ich mir auch schon gedacht, aber gibt es da denn eine Möglichkeit das zu beeinflussen?
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.464 Beiträge
 
Delphi 12 Athens
 
#4

AW: Firebird - where Bedingung mit Bedingung

  Alt 3. Sep 2024, 16:04
Deshalb doch die Variante mit iif() gepostet.
  Mit Zitat antworten Zitat
lxo

Registriert seit: 30. Nov 2017
288 Beiträge
 
Delphi 12 Athens
 
#5

AW: Firebird - where Bedingung mit Bedingung

  Alt 3. Sep 2024, 16:59
Achso, ne das hilft auch nicht.
Funktioniert nur bei Konstanten-Werten mit iif.
Wenn ich dort Felder angebe macht der sogar 5264 reads.

Setze ich die selben Felder in mein oben genanntes Konstrukt wo 604 reads gemacht werden.
Macht der auch mit den Feldern nur 604 reads.


** Mit Case gleiches Ergebnis wie mit iif.
  Mit Zitat antworten Zitat
lxo

Registriert seit: 30. Nov 2017
288 Beiträge
 
Delphi 12 Athens
 
#6

AW: Firebird - where Bedingung mit Bedingung

  Alt 3. Sep 2024, 17:27
Hier nochmal runtergebrochen aufs wesentliche wie es bei mir aussieht.
Hab auch schon statt iif mit einer Function probiert aber auch so viele Ergebnisse.
Mit Plan auch schon hin und her probiert aber find da auch keine Lösung.


** Hintergrund warum ich das mache.
Durch die Eigenschaft "Global" in der Tabelle1 sollen die Werte aus Tabelle3 immer aus dem Main aus Tabelle2 (Es kann immer nur ein Main in Tabelle2 geben) geladen werden.
Ansonsten wenn nicht "Global" lies wie gehabt.

Dieses Statement habe ich in eine View gepackt um den Zugriff auf Tabelle3 im Programm zu manipulieren. (Wollte mir ersparen in Delphi alles anpassen zu müssen)

Das funktioniert auch wie gewünscht, jedoch bisschen langsam durch die mehrfachen reads die meiner Meinung nach unnötig gemacht werden.



Code:
select T1.ID as T1_ID,
       T2.ID as T2_ID,
       T3.WERT
from TABELLE1 T1
cross join TABELLE2 T2
inner join TABELLE3 T3 on T3.T1_ID = T1.ID
-- 604 reads
( ( T1."GLOBAL" and
  ( T3.T2_ID = ( select T2_TEMP.ID
                 from TABELLE2 T2_TEMP
                 where T2_TEMP.MAIN))) or
  ( not T1."GLOBAL" and
  ( T3.T2_ID = T2.ID)))

-- 314 reads
( T3.T2_ID = ( select T2_TEMP.ID
                 from TABELLE2 T2_TEMP
                 where T2_TEMP.MAIN))
-- 290 reads
( T3.T2_ID = T2.ID)


-- iif() 5264 reads
      T3.T2_ID = iif( T1."GLOBAL", ( select T2_TEMP.ID
                                     from TABELLE2 T2_TEMP
                                     where T2_TEMP.MAIN), T2.ID)

where T1.ID = 111 and
      T2.ID = 20

Geändert von lxo ( 3. Sep 2024 um 17:32 Uhr)
  Mit Zitat antworten Zitat
Frickler

Registriert seit: 6. Mär 2007
Ort: Osnabrück
591 Beiträge
 
Delphi XE6 Enterprise
 
#7

AW: Firebird - where Bedingung mit Bedingung

  Alt 3. Sep 2024, 17:45
Statt nem View ne GTT als "poor man's materialized view"? Muss natürlich auch gefüllt werden (alles zusammen in EXECUTE BLOCK, oder möglicherweise in einem Trigger).
  Mit Zitat antworten Zitat
lxo

Registriert seit: 30. Nov 2017
288 Beiträge
 
Delphi 12 Athens
 
#8

AW: Firebird - where Bedingung mit Bedingung

  Alt 3. Sep 2024, 20:17
Statt nem View ne GTT als "poor man's materialized view"? Muss natürlich auch gefüllt werden (alles zusammen in EXECUTE BLOCK, oder möglicherweise in einem Trigger).
Wie meinst du das, alles in einem Execute Block?
GTT sind ja Transaktions- oder Verbindungs-gebunden.
Hab ich da denn die Möglichkeit in einem trigger einer normalen Tabelle die GTT für jede Transaktion bzw. Verbindung zu aktualisieren?
Ich muss ja sicherstellen das der Inhalt bei jeder Verbindung aktuell ist, weil bei jedem select das GTT neu aufbauen ist bestimmt noch langsamer als meine bisherige Lösung mit doppelten reads oder?
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.490 Beiträge
 
Delphi 7 Professional
 
#9

AW: Firebird - where Bedingung mit Bedingung

  Alt 3. Sep 2024, 21:02
Ginge sowas?
SQL-Code:
select * from tabelle where id = ((:condition and (id = 1))
union all
select * from tabelle where id = (not :condition and (id = 20))
Zitat von lxo:
Warum macht Firebird bei der verschachtelten Bedingung 604 reads und nicht 314?
Meiner Meinung nach ist das korrekt so wie es ist:
Code:
1. Wherebedingung
-- 314 indizierte reads auf die Tabelle
T.ID = 1
Code:
2. Wherebedingung
-- 290 indizierte reads auf die Tabelle
T.ID= 20
314 Reads + 290 Reads = 604 Reads
Code:
3. Wherebedingung -> Reads = Summe der Reads aus Wherebedingung 1 und Wherebedingung 2.
-- 604 indizierte reads auf die Tabelle
            ( ( TRUE and
              ( T.ID = 1)) or
              ( not TRUE and
              ( T.ID= 20)))
Firebird arbeitet hier praktisch die beiden Wherebedingungen ab und fügt deren Ergebnisse zusammen. Der Aufwand für die Datenbank für das Ausführen der kombinierten Wherebedingung ist genauso hoch wie der Aufwand für das Ausführen der einzelnen Bedingungen. Die Reads sind wohl eher abhängig von der Datenmenge, vermutlich gibt es mehr Sätze mit ID = 1 als mit ID = 20 und deshalb unterscheiden sich die Reads. Bei geänderten Datenverhältnissen kann sich das dann auch mal verschieben.
  Mit Zitat antworten Zitat
lxo

Registriert seit: 30. Nov 2017
288 Beiträge
 
Delphi 12 Athens
 
#10

AW: Firebird - where Bedingung mit Bedingung

  Alt 3. Sep 2024, 21:12
Ginge sowas?
SQL-Code:
select * from tabelle where id = ((:condition and (id = 1))
union all
select * from tabelle where id = (not :condition and (id = 20))
Zitat von lxo:
Warum macht Firebird bei der verschachtelten Bedingung 604 reads und nicht 314?
Meiner Meinung nach ist das korrekt so wie es ist:
Code:
1. Wherebedingung
-- 314 indizierte reads auf die Tabelle
T.ID = 1
Code:
2. Wherebedingung
-- 290 indizierte reads auf die Tabelle
T.ID= 20
314 Reads + 290 Reads = 604 Reads
Code:
3. Wherebedingung -> Reads = Summe der Reads aus Wherebedingung 1 und Wherebedingung 2.
-- 604 indizierte reads auf die Tabelle
            ( ( TRUE and
              ( T.ID = 1)) or
              ( not TRUE and
              ( T.ID= 20)))
Firebird arbeitet hier praktisch die beiden Wherebedingungen ab und fügt deren Ergebnisse zusammen. Der Aufwand für die Datenbank für das Ausführen der kombinierten Wherebedingung ist genauso hoch wie der Aufwand für das Ausführen der einzelnen Bedingungen. Die Reads sind wohl eher abhängig von der Datenmenge, vermutlich gibt es mehr Sätze mit ID = 1 als mit ID = 20 und deshalb unterscheiden sich die Reads. Bei geänderten Datenverhältnissen kann sich das dann auch mal verschieben.
Mein Gedanke war aber wenn die zweite Bedingung eh schon false ist, wozu wird da noch was gelesen. Die könnte er ja eigentlich ignorieren.
Macht der ja auch wenn ich iif mache, aber nur mit konstanten Werten.
  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 14:28 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