![]() |
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? |
AW: Vorhandensein eines Records prüfen
Wenn der Query-Plan der gleiche ist, dann kann das eine nicht schneller sein als das andere.
|
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: ![]() 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; |
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. |
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. |
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. |
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) ;) |
AW: Vorhandensein eines Records prüfen
wie wäre es mit
SQL-Code:
ganz klar schneller als
select distinct 1 from mytable where myid is not null
Code:
wobei die Zeiten von Jasocul ja wirklich jehnseits von gut und böse sind.
select Count(*)
Gruß K-H |
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. |
AW: Vorhandensein eines Records prüfen
Zitat:
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 |
AW: Vorhandensein eines Records prüfen
Hallo,
es geht darum, festzustellen, ob es mindestens einen Record einer bestimmten Where-Klausel gibt. Select First 1 From RechnungsId From RechnungsPosition Where RechnungsId=1 |
AW: Vorhandensein eines Records prüfen
Sorry, aber ich habe die Frage wie p80286 offensichtlich ebenfalls falsch verstanden. Dafür kannst Du den Hack vergessen, der ist nur um zu prüfen, ob überhaupt ein Datensatz in der Tabelle vorhanden ist.
Und wie Du schon selbst korrekt ergänzt hast, funktioniert das nur für Tabellen ohne gelöschte Datensätze zuverlässig. Damit es nach Löschung wieder funktioniert ist ein Backup mit "Garbage collection" (gbak -g) und anschliessendes Restore notwendig. |
AW: Vorhandensein eines Records prüfen
Zitat:
SELECT FIRST muß doch eventuell auch die Sortierung beachten? (wenn die DB daher auch noch erst sortiert, muß erstmal alles gesucht werden) Mit DISTINCT wird es dann noch schlimmer. Und bei COUNT muß sowieso alles erstmal gesucht werden. 1 oder true statt * im SELECT dürfte auch etwas sparen, wenn nicht alle Felder der gefundenen/verwendeten Records geladen werden brauchen. (falls das DBMS nicht schon schlau genug ist und mitbekommt, dass es am Ende eh keines der Felder braucht und sie somit weg lässt) EXSIST sollte da doch eventuell besser laufen, da dort alles egal ist |
AW: Vorhandensein eines Records prüfen
Hallo,
SELECT FIRST muß doch eventuell auch die Sortierung beachten? Eventuell, wenn ich ein Order By machen würde, aber für das einfache Erkennen des Vorhandenseins mindestens eines Records ist das ja nicht notwendig. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:53 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