Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Vorhandensein eines Records prüfen (https://www.delphipraxis.net/193294-vorhandensein-eines-records-pruefen.html)

hoika 13. Jul 2017 07:35

Datenbank: FB • Version: 2.01 • Zugriff über: egal

Vorhandensein eines Records prüfen
 
Hallo,
oft muss ich prüfen, ob mindestens ein Record in einer Tabelle vorhanden ist

Version 1
die klassische Vorgehensweise: Select Count(*)

Version 2
wir nutzen "neue" FB-Funktionen
Select First 1 Wert From Tabelle

Version 3
tricky Ausnutzung von Firebird-Besonderheiten beim Exists
Select 1 From RDB$DataBase Where Exists(Select Wert From Tabelle)
Wobei das durch Version 2 mit dem First ja jetzt wohl gegenstandslos ist


Das Where habe ich weggelassen, auf dem Where-Feld ist auf jeden Fall ein Index.
Die Suche läuft also auf jeden Fall über einen Index
(viele Datensätze, gute Selektivität des Suchfeldes)

Mein Gefühl sagt mir, dass Version 2 die schnellste Variante ist.
Der Query-Plan ist aber bei V1 und V2 der gleiche.


Was meint Ihr?

Neutral General 13. Jul 2017 08:22

AW: Vorhandensein eines Records prüfen
 
Wenn der Query-Plan der gleiche ist, dann kann das eine nicht schneller sein als das andere.

DelphiBandit 13. Jul 2017 08:37

AW: Vorhandensein eines Records prüfen
 
Wenn ich das richtig verstanden habe, dann interessiert Dich nur, ob ein/mehrere Datensätze da sind oder die Tabelle noch leer ist. Korrekt?

Hätte dazu folgenden Hack in meinen Firebird-Bookmarks gefunden. Ist rasend schnell, setzt aber eingeschaltete Statistics und einen Primärindex voraus. Alles was 0 liefert wurde in den Statistics bisher noch nicht angefasst.

Quelle: http://www.firebirdfaq.org/faq5/

Wobei es nicht ausgeschlossen ist, dass die Datenbank-Engine solch Konstrukte vielleicht auch selbst intern nutzt ;)

Code:
SELECT RDB$RELATIONS.RDB$RELATION_NAME,
       CASE
         WHEN RDB$INDICES.RDB$STATISTICS = 0 THEN 0
         ELSE CAST(1 / RDB$INDICES.RDB$STATISTICS AS INTEGER)
       END
  FROM RDB$RELATIONS
  LEFT JOIN RDB$RELATION_CONSTRAINTS
       ON RDB$RELATIONS.RDB$RELATION_NAME = RDB$RELATION_CONSTRAINTS.RDB$RELATION_NAME
       AND RDB$CONSTRAINT_TYPE = 'PRIMARY KEY'
  LEFT JOIN RDB$INDICES
       ON RDB$RELATION_CONSTRAINTS.RDB$INDEX_NAME = RDB$INDICES.RDB$INDEX_NAME
WHERE RDB$VIEW_BLR IS NULL AND RDB$RELATION_ID >= 128
AND  RDB$RELATIONS.RDB$RELATION_NAME = 'HIER DEN TABELLENNAMEN'
ORDER BY 1;

hoika 13. Jul 2017 08:43

AW: Vorhandensein eines Records prüfen
 
Hallo,
setzt aber eingeschaltete Statistics und einen Primärindex voraus
Was sind denn ausgeschaltete Statistics?

Wobei es nicht ausgeschlossen ist, dass die Datenbank-Engine solch Konstrukte vielleicht auch selbst intern nutzt
Schon möglich ;)

Wenn der Query-Plan der gleiche ist, dann kann das eine nicht schneller sein als das andere.
Doch, wenn ich ein Count(*) machen, muss er alle passenden Einträge zusammenzählen,
bei First 1 kann die Indexsuche nach dem ersten Treffer abbrechen.
Der Query-Plan ist aber trotzdem der gleiche.

DelphiBandit 13. Jul 2017 08:48

AW: Vorhandensein eines Records prüfen
 
OK. Etwas im Wort vergriffen, aktuelle/aktualisierte Statistics trifft es besser.

Kannst ja einfach mal mit dem SQL und einer vollen Tabelle testen, ob es noch ein Quentchen schneller ist als mit FIRST 1.

Jasocul 13. Jul 2017 08:49

AW: Vorhandensein eines Records prüfen
 
Interessant ist es eigentlich nur für Abfragen auf Tabellen mit großen Datenmengen.
Bei leeren Datenmengen ist der Unterschied normalerweise zu vernachlässigen. Das dürfte sich in allen Fällen im Millisekunden-Bereich bewegen.

Ich habe mal alle drei Verfahren auf MS-SQL getestet. Die Tabelle enthält über 40 Mio Datensätze.

Select Count(*) ist indiskutabel (Testserver: 50 Sekunden. Live-Server knapp 3 Sekunden).

Die beiden anderen Varianten haben keinen messbaren Unterschied und befinden sich im einstelligen Millisekunden-Bereich.

Der Hack von DelphiBandit funktioniert nur bei eingeschalteter Statistik, wie er schon selbst geschrieben hat. Meines Wissens kann das Ergebnis trotzdem falsch sein, da die Statistics nicht permanent aktualisiert werden.

hoika 13. Jul 2017 09:57

AW: Vorhandensein eines Records prüfen
 
Hallo,
Select Count(*) ist indiskutabel (Testserver: 50 Sekunden. Live-Server knapp 3 Sekunden).

Hier kommt es auch an, wie viel der Server zählen muss (=Anzahl der Ergebnisse).

Aber wir reden ja nicht von MS-SQL, sondern von einem richtigen DB-Server (Firebird) ;)

p80286 13. Jul 2017 10:09

AW: Vorhandensein eines Records prüfen
 
wie wäre es mit
SQL-Code:
select distinct 1 from mytable where myid is not null
ganz klar schneller als
Code:
select Count(*)
wobei die Zeiten von Jasocul ja wirklich jehnseits von gut und böse sind.

Gruß
K-H

hoika 13. Jul 2017 10:57

AW: Vorhandensein eines Records prüfen
 
Hallo,
select distinct 1 from mytable where myid is not null ganz klar schneller als
Das liefert doch aber zurück, ob es überhaupt einen Eintrag in der Tabelle gibt.

Ich denke, dass First schneller als Distinct ist.
Das Distinct muss ja erst die Ergebnismenge ermitteln, um dann darauf Distinct auszuführen.

Bei der SELECT RDB$RELATIONS.RDB$RELATION_NAME Abfrage stellt sich für mich die Frage,
was passiert, wenn der letzte Eintrag meiner Ergebnismenge (where myid=X) gelöscht wird.
Ist die Statistik dann trotzdem korrekt, zeigt also keine Einträge an,
oder wird der gelöscht Eintrag immer nicht berücksichtigt?.

Any record that has had its primary key modified will appear twice if the old version has not been garbage collected and deleted records will continue in the count until they are garbage collected.
Das sieht hier eben so aus, als ob auch die Garbage-Einträge mit gezählt werden.

p80286 13. Jul 2017 15:21

AW: Vorhandensein eines Records prüfen
 
Zitat:

Zitat von hoika (Beitrag 1376630)
Hallo,
select distinct 1 from mytable where myid is not null ganz klar schneller als
Das liefert doch aber zurück, ob es überhaupt einen Eintrag in der Tabelle gibt.

das wolltest du doch? oder hab ich da was mißverstanden?

Wenn Du aus einem (Delphi) Programm heraus diese Frage stellst, reicht es ja auch nur den ersten Datensatz abzuholen, und den evtl vorhandenen Rest vergißt Du einfach??

Gruß
K-H


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:23 Uhr.
Seite 1 von 2  1 2      

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