![]() |
Datenbank: Firebird • Version: 2.1 • Zugriff über: Egal
[FB 2.1] Schnelle Alternative zu Count(*) ?
Hi,
Ich habe eine Tabelle mit 1 Mio Einträgen. In einer App soll ständig die Anzahl der Zeilen dieser Tabelle angezeigt werden. Ein 'SELECT COUNT(*) FROM TABELLE' dauert ewig. Frage: Gibt es eine schneller Alternative, um die Zeilenanzahl einer Tabelle zu ermitteln? Ich vermute, es geht irgendwie über die $RDB-Tabellen. Hat jemand einen Hint? |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
SQL-Code:
statt
Select count(<pk>)
SQL-Code:
select Count(*)
|
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
Tut aber auch nicht weh wenn man die SQLs mit MSSQL, Sybase oder Ora teilen will... |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Hi Markus und Elvis,
Danke für den Tipp. Klappt nur leider nicht, d.h. es ist immer noch genauso lahm. |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
|
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Hi alzaimar,
die Anzahl der Datensätze steht doch in deiner Datenbankkomponente (ADOquery.... zumindest bei denen die ich bisher verwendet habe). Vielleicht lieg jetzt auch falsch, aber 3 Zeilen ist es Wert. Viele Grüsse! |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Hallo Hazard999,
nein, das ist nicht genau. Ich habe mir nun so beholfen, das ich die Anzahl in einer separaten Tabelle (1 Zeile, 1 Feld 'RowCount') per Trigger auf dem Laufenden halte. @R2009: Du meinst die 'Recordcount'-Eigenschaft. Rate mal, was die macht :zwinker: [ ] Sie weiss einfach, wie viele Zeilen in der Tabelle stehen [ ] Sie liest alle Zeilen ein (per SELECT * FROM) und zählt sie dann. (Tipp: Nur eine Antwort ist richtig) Bonusfrage: Geht das schneller? :mrgreen: |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
Ernsthaft, manche fehlende Features sind böse genug, dass man sie als Bug ansehen muss. Habe glücklicherweise noch nie ein uneingeschränktes Count(...) in FB gebraucht... :angle2: |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Notfalls basteslt du dir halt eine eigene Systemtabelle, in welche du die Anzahl per Trigger updatest
( auch wenns der Normalisierung widerspricht) |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Meine, das Firebird den Index ohne WHERE gar nicht verwendet.
SQL-Code:
Habe aber keine so große Testtabelle, um den Unterschied zu testen.
Select COUNT(<pk>) FROM <table> WHERE 1=1
€: Scheint langsamer... Where kostet wohl mehr als es bringt (falls das mit dem Index s.o. stimmt) |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Hi,
ob man die Verwendung eines Index erzwingt oder nicht, macht IMHO keinen Unterschied. Ein Count von 1.000.000 Datensätzen erzeugt mit und ohne Index 1.000.000 Reads. Ich denke, die Variante mit den Triggern ist die wohl einzig machbare. Cu, Frank |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Hi Leute,
ich hab das jetzt mit den Triggern so umgesetzt. Mich wundert es nur ein wenig, denn Firebird selbst sollte doch wissen, wie viele Zeilen denn nun in der Tabelle sind bzw. Blätter im B-Baum des PK. Die Trigger-Lösung ist leider nicht ganz so hübsch, weil ich mir dadurch eigentlich überflüssige Deadlock-Kandidaten einhandle bzw. unnötige Locks. |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
|
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Dann müssen es aber verdammt viele sein.
|
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
Zitat:
|
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
|
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
Gruss Kh |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
|
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
Wie soll ein Index beim Zählen aller Datensätze behilflich sein? Erst bei einer Einschränkung der Ergebnismenge mit Where oder beim Sort wird ein Index benötigt. Frank |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
|
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
Das Verfahren würde wirklich nur bei einem einfachen Count funktionieren. Aber das ist jetzt wohl Spekulation und vielleicht hast du ja recht. Ich habe mit IBExpert das Verhalten mal verglichen (bei ca. 700.000 Records). Die Zeiten sind identisch, wenn ich select count(PK) from table bzw. select count(pk) from table where pk > 0 nehme. Der Index wird im 2. Statement benutzt. Frank |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
Ohne Index muss man wirklich alle Zeilen durchlaufen (oder die geheime Tabelle mit den Metadaten finden). Mit Index zähle ich nur die Anzahl der B-Tree-Seiten und multipliziere sie mit der Größe eines Indexelementes. B-Tree-Seiten von Index-Strukturen wissen zudem, wie viele Elemente sie enthalten. Ich kenne zwar die FB-Implementierung nicht, kann mir aber nicht vorstellen, das FB bei B-Trees andere Wege schreitet, als der gängige und bewährte Standard. Der Weg über die B-Tree-Seiten macht also das Zählen um einen konstanten Faktor schneller (z.B. f=2000 für einen INTEGER-PK), denn ich muss nicht N Zeilen zählen, sondern nur N/f Seiten. Weiterhin haben Indexstatistiken Informationen über die Gesamtanzahl der Einträge, sowie mindestens die Anzahl der unterschiedlichen Einträge (häufig noch zusätzliche Informationen), um beim Optimieren bzw. Erstellen des Queryplans den besser strukturierten Index zu bevorzugen. Es müsste also theoretisch gehen. Allerdings kann ich mir nicht vorstellen, einen solchen Sonderfall in der Erstellung des Queryplans für ein 'COUNT(*)' einzubauen. Kein TPC-Benchmark würde das würdigen. Dann doch lieber die geheimen Metatabellen zugänglich machen. Irgendwo muss doch einfach stehen, wieviel Records in dieser Tabelle stehen. Ob nun mit oder ohne PK. Dammich, verdammt :wall: :stupid: PS: Ich bekomm tatsächlich beim Programmstart ab und an ein Deadlock Problem. Einmal. Immer am Anfang. :gruebel: Muss an mir liegen. Ich schau mir das morgen nochmal an. |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
|
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
Frank [EDIT] Hmmm, habe jetzt noch mal count(*) gemacht, ist jetzt auch so schnell. Wahrscheinlich hält FB die Daten auch nach einem Disconnect noch länger im Cache. [/EDIT] |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Hallo alzimar,
könnte man nicht den aktuellen Generator-Wert auslesen und die gelöschten Datensätze davon abziehen? Bis bald Chemiker |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
|
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Hallo mkinzler,
z.B.: 2 Generator mitlaufen lassen für gelöschte Datensätze, oder in einem anderen Bereich des 1 Generators. Ist nur so eine Idee. Bis bald Chemiker |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
|
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Hallo mjustin,
und wie ist das bei COUNT? Bis bald Chemiker |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
Wie wäre es, z.B. anhand eines Zeitstempels (Datum der Satzanlage) nur die aktuellen Sätze abzufragen? Also wenn z.B. die Daten bis April 2009 sich nicht mehr allzusehr ändern, macht man ein Select count(*) from tabelle where creationdate >= '01.05.2009' Und addiert eine bereits bekannte Satzanzahl für alle davor liegenden Sätze auf. Oder man geht etwas weg von der Datenbank, erzeugt in der Anwendung eine 'Satz erzeugt' oder 'Satz gelöscht' Message an einen zentralen Prozess (Application Server, simplen Telnetserver, whatever) und dieser sammelt die Messages und aktualisiert die Anzahl, entweder in einer Datenbanktabelle die nur einen Satz enthält, oder indem er in einer Antwortmessage die aktuelle Zahl zurückliefert. |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Hallo,
ich wollte der Vollständigkeit halber doch noch mal meine Tesergebnisse zu count zusammenfassen. Ich wollte es einfach wissen. Es war etwas kompliziert, da der erste Aufruf immer am längsten dauert. Dann greift der DB Cache. Für eine zweiten Versuch müsste man den Rechner neu starten, da auch nach ShutDown und Neustart des Servers die Abfragen schneller gehn. Wahrscheinlich greift hier der System Cache vom OS. Die Ausführungsgeschwindigkeit für 1. select count(*) 2. select count(pk) 3. select count(pk) where pk > 0 ist in etwa gleich. Tabelle hatte ca. 750.000 Datensätze. Test 1 und 2 lag zwischen 500 un 540 ms. test 3 lag etwa bei 620 ms. Ich habe das ganze 30 mal durchgeführt. So, wie es aussieht, verlangsamt die zusätzliche Verwendung des Indexes (Test 3) den Prozess sogar noch. Frank |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
Würde einem DBMS-Optimierer jedenfalls zutrauaen, dass er selbst auf die geheimen Tabellen zugreifen würde, wenn da Zahlen geführt würden. Grüße // Martin |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Hallo,
wie schon weiter oben gesagt wurde, läuft das Count(*) immer innerhalb einer Transaktion. Durch die MGA von Firebird gibt es keine "feste Recordzahl". Inwieweit man dem Nutzer sagen will 751.345, 751.346 ... Einträge sind drin, steht zur Frage. Heiko |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
Auf der oben verlinkten FB Page wurde da schon auf sehr verzweifelte Hacks zurückgegriffen, also wird FB hier wohl nix bieten. Die Frage ist halt, ob Trigger für jedes Delete und Insert auf Row-Ebene vertetbar wären. Dann könnte sich Alzaimar selbst eine Meta table führen, in der zu jeder Tabelle die Records in der aktuellen Transaktion stehen. Ob es dadurch zu mehr Deadlocks kommt bezweifle ich, schließlich schreibt man da ja nur, wenn man eh schon schreibt (insert/delete). Trotzdem ganz schön bitter, IMO... |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
SQL-Code:
Der Optimizer, der sich sonst einen Wolf optimiert (Hä? Wie? 'Der mit dem Wolf optimiert?' :gruebel: ), erspart sich das, vermutlich aus den von mir genannten Gründen.
SELECT rows FROM sysindexes WHERE id = OBJECT_ID('table_name') AND indid < 2
Ich verstehe die Argumentation mit MGA nicht. Genauso, wie MGA mir eine (meine) Sicht auf alle Daten liefert, könnte das doch genauso mit der Zeilenanzahl funktionieren. Schließlich gibt es Tabellen für Tabellen, Felder, Views usw. Wieso steht in der Tabellentabelle nicht auch die Tabellengröße drin? Ich kapiere es nicht. |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Wegen der Versionierung wären dann auch mehrere Metadatenversionen von Nöten
|
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Zitat:
Es kommt zwar nicht zu einem Deadlock, aber sobald zwei Insert-Trigger gleichzeitig die alte Satzzahl lesen, und der erste Trigger diese Zahl (erhöht ums eins) erfolgreich zurückschreibt und committed, kann der zweite Insert Trigger den ursprünglichen Satz nicht mehr updaten (da er sich dadurch verändert hat), und muss aufgeben... |
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Da die Trigger in Transkationen laufen, sehe ich das Problem nicht. Allerdings wäre diese tabelle dann auch "versioniert" (mehrere konkurrierende Zugriffe -> mehrere Datensätze/Werte)
|
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Ich hatte aber Deadlocks, und zwar immer beim Programmstart. Heute war ich out of office, aber morgen gehts der Deadlocke an den Sack. Meine Lösung besteht aus einer Tabelle mit einer Zeile und einem Feld ('RowSize') sowie zwei Triggern (BeforeInsert, BeforeDelete). Am Anfang der SW kommt manchmal genau 1x ein Deadlock. Danach nicht nochmal.
|
Re: [FB 2.1] Schnelle Alternative zu Count(*) ?
Hallo,
was passiert, wenn nach dem Insert ein Rollback gemacht wird ? ? Dann wird natürlich kein OnDelete-Trigger aufgerufen. Heiko |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:50 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