![]() |
Datenbank: Firebird • Version: 2.5 • Zugriff über: IBDAC
Firebird Datenbankgröße
Hallo,
in Anlehnung an mein anderes Problem ( ![]() Ich bin mit der Datenbankgröße auf der Platte nicht wirklich zufrieden. Gegeben:
Delphi-Quellcode:
21000000 Datensätze in Tabelle
CREATE TABLE T_RECORD_DATA (
F_PARAMETER_ID ID /* ID = INTEGER NOT NULL */, F_TIMESTAMP_UNIX INTEGER_NORMAL /* INTEGER_NORMAL = INTEGER NOT NULL */, F_POWER_STATE INTEGER_NORMAL /* INTEGER_NORMAL = INTEGER NOT NULL */, F_VALUE STRING10 /* STRING10 = VARCHAR(10) NOT NULL */ 1,65 GB Plattenplatz Datenquelle: Technisches Gerät mit (angeblich) 128MB internem Speicher und 25% Belegung :shock: Wo kommen die extremen Größendifferenzen her? Der Index belegt nicht wirklich viel. Etwa 5% der Gesamtgröße geschätzt nach 2 Versuchen in leere DB (3,6 MB) sowohl mit Index als auch ohne. Wie kann ich die Datenbankgröße verkleinern? Betroffen von der Datenflut ist nur diese Tabelle. Dies ist nur ein Gerät. Max 500 sollen möglich sein. Das wären 1,65*4(Belegung 100%)*500 = 3,3 TB (größte bekannte FB Datenbank hat rund 980 GB)...Klar gibt es da wieder Möglichkeiten (1 DB je Gerät etc.). Mir ist nur diese Ausgangsbasis zu viel. Danke für Info´s... 8-) |
AW: Firebird Datenbankgröße
1.)Bei Updates eines Datensatzes wird eine neue Kopie des Datensatzes (neue Version) angelegt.
2.)Gelöschte Datensätze werden nicht gelöscht sondern markiert. zu 1.) Bei einem Sweep werden die Versionen bereinigt. zu 2.) Backup/Restore |
AW: Firebird Datenbankgröße
Geht das nicht mit
Code:
?
gfix -sweep
|
AW: Firebird Datenbankgröße
Ja:
Code:
gfix -user SYSDBA -password masterkey dbserver:/db/mydb.fdb -sweep
|
AW: Firebird Datenbankgröße
Danke. 8-)
Die Datensätze werden nur per Insert eingefügt. Eine Bearbeitung (update) ist nicht vorgesehen. Die Datenbankgröße ist die nach den 21 Mio Insert incl Index. |
AW: Firebird Datenbankgröße
Hast Du mal nachgerechnet?
21 Mio Datensätze in 25% von 128MB Speicher sind irgendwie nicht ganz so viele Bytes pro Datensatz. Genauer gesagt: 1.6 Bytes. Zitat:
Was wir hier haben sind ca. 23 Bytes reine Nutzdaten. Das ergibt dann schon mal in Summe 460 MB (21 Mio recs # 23 Bytes). Pro Index über einen 4-Byte-Integer kommen da dann noch 84 MB + Overhead hinzu. Ich kenne FB jetzt nicht, aber ich würde pro Record einen Overhead von ca 10-15 Bytes annehmen, das wären dann also ca. 40 Bytes Brutto ohne Index, also ungefähr 800MB. Dann noch der Index mit 80MB + X Overhead und wir sind schon nahe am GB. Na, vielleicht ist der Overhead doch etwas höher. |
AW: Firebird Datenbankgröße
Danke für deine Berechnungen. :P
Zitat:
Zitat:
Zitat:
Ich habe schon mit varchar(1) statt Integer für den PowerState experimentiert... ohne nennenswerte Platzgewinne. :? |
AW: Firebird Datenbankgröße
Ich sage ja: FB hat eben noch einen höheren Record-Overhead. Auch bei den Indexen ist es doch etwas mehr als die reinen Nutzdaten.
Heutzutage ist ja Performance wichtiger als Speicher und wenn das bei FB eben so ist, dann ist es doch gut. Ich hab mal eben eine Test-DB auf einem SQL-Server erzeugt. Das verbrät mit einem Index so ziemlich genau ein GB. |
AW: Firebird Datenbankgröße
werden nach dem Insert keine Änderungen an den Daten vorgenommen und keine weiteren Inserts durchgeführt? Bzw. wenn dann erst ein Delete * from... bzw. ein großer Insert mit Massendaten?
Dann könnte folgendes was bringen: Firebird speichert die Daten ja auf "Pages" die aber nicht zu 100% gefüllt werden, um Lücken für spätere Inserts zu lassen um wegen dem Index nicht alles umsortieren zu müssen. Macht man aber nur einmal einen großen Insert und ändert die Daten hier kaum noch, kann man auch die Seiten komplett füllen und damit wir die Datei an sich kleiner. Mach mal ein gstat -data <Database>. Dann sollte so was raus kommen:
Code:
Wenn hier viele Seiten nur 60-80% gefüllt sind, verlierst Du entsprechend Platz.
CONFIGREVISIONSTORE (213)
Primary pointer page: 572, Index root page: 573 Data pages: 2122, data page slots: 2122, average fill: 82% Fill distribution: 0 - 19% = 1 20 - 39% = 0 40 - 59% = 0 60 - 79% = 79 80 - 99% = 2042 Ändern kannst Du das über gfix: ![]() gfix -use FULL database_name [edit]: Vorteil ist, dass im Grunde die Lesegeschwindigkeit steigt, da weniger Pages gelesen werden müssen, nachteil: Inserts dauern auf grund der Index-Optimierung länger. Bei großen Inserts daher besser den Index deaktivieren und anschließend wieder neu aufbauen... Weiterhin kann die PageSize an sich auch ein Problem sein, wenn diese nicht mit der Sektorengröße auf der Platte zusammen passt - hier sollte aber der Windows-Explorer in neueren WIndows-Versionen die entsprechenden Informationen auch ausgeben können. |
AW: Firebird Datenbankgröße
@Lemmy: Das würde ich nur bei einer Read-Only Datenbank machen.
|
AW: Firebird Datenbankgröße
@Thomas: ich habe das ehrlich gesagt noch nie gemacht - aber wo ist der Unterschied zwischen einer (eingestellten) Read-Only DB und einer DB in die ich keine Inserts mache? Sortiert FB hier dennoch immer wieder Daten um?
|
AW: Firebird Datenbankgröße
Er macht ja Inserts
|
AW: Firebird Datenbankgröße
Und die sind immer am Ende? So von wegen Timestamp und Index drauf. Weiß jetzt nicht, wie FB das macht, aber die Daten werden ja wohl ans Ende gepackt,
|
AW: Firebird Datenbankgröße
Nein. Wenn vorher ein datensatz gelöscht wurde, wird der Speicherplatz für neue Inserts wieder verwendet.
|
AW: Firebird Datenbankgröße
Zitat:
|
AW: Firebird Datenbankgröße
Zitat:
128MB durch 21 Mio = 6 Bytes der Index besteht auf 4 Byte Nutzdaten Aufbau eines Index Records: ![]() struct btree_nod { UCHAR *nodePointer; USHORT btn_prefix; USHORT btn_length; SLONG pageNumber; UCHAR *data; RecordNumber recordNumber; bool isEndBucket; bool isEndLevel; 1+2+2+4+4+4+1+1 = 19 Byte bei 4 Byte Nutzlast sind dann 400 MB , dazu kommt dass die Indexe in Pages verwaltet werden die meist nicht ganz gefüllt werden Plus Overhead um die Pages zu verwalten , 2 Indizes laut dem anderen Thread also über 800MB Record Header : (auch von der IBexpert seite) struct rhd { SLONG rhd_transaction; SLONG rhd_b_page; USHORT rhd_b_line; USHORT rhd_flags; UCHAR rhd_format; UCHAR rhd_data[1]; }; 4+4+2+2+1+ Nutzlast 36 Bytes bei 21 Mio Record 756 MB Plus 800 MB Index so dass das mit den 1.65 GB schon hinkommt mfg Hannes |
AW: Firebird Datenbankgröße
Ich kann mir nicht vorstellen, dass niemals gelöscht wird, sprich die Tabelle ins Unendliche wachsen darf/kann.
Firebird hat auch keinen Clustered Index wie in SQL Server bzw. eine Index-Organized Table wie in Oracle. |
AW: Firebird Datenbankgröße
Zitat:
Die sollen in der DB verbleiben. Quasi die letzten 10 Jahre. Wenn die DB an dieser Stelle ankommt werden die ersten entfernt. Beim aktuellen Beispiel wären das 1,6GB zu 0,75 = x zu 10 -> 21,3GB (0,75 Jahre im Gerät bei 10 Jahre gesamt) Inzwischen ist die Entscheidung gefallen, daß jedes Gerät seine eigene DB für die Record Daten bekommt. Damit sind ein paar Probleme vom Tisch (Gesamtgröße) PS: Ich rechne lieber mit dem WorstCase als später in Probleme zu laufen weil man sich nicht richtig Gedanken gemacht hat. Zitat:
|
AW: Firebird Datenbankgröße
In welcher Granularität musst du die Messdaten aufbewahren?
Bei Timeseries Anwendungsfällen geht man in der Regel so vor, dass periodisch Daten von einer höheren Auflösung in kleinere Auflösungen aggregiert wird und im selben Kontext Daten der höheren Auflösung gelöscht werden. Außer du bist im Bereich Garantie wo du die feingranularen Daten zur Nachvollziehbarkeit benötigst. Bzgl. Datenbank je Gerät. Im Prinzip musst du dann X Datenbanken bzgl. Schemastruktur auf einem entsprechenden Stand halten, jede Datenbank sichern etc., bei einem Firebird/ODS Upgrade diese sichern/wiederherstellen etc. Dann hast du vielleicht auch Stammdaten, die jedem Gerät gemein sind. Wie machst du das? Je nach Datenvolumen and Anwendungsfall haben hier (für Zeitreihen) BigData-Lösungen ala Cassandra absolut ihre Daseinsberechtigung. Aber das ist eine ganz andere Welt ... |
AW: Firebird Datenbankgröße
Zitat:
Gruß K-H |
AW: Firebird Datenbankgröße
Hallo Thomas...
ich bin ein wenig von der Größe überfahren worden. Im Leben hätte ich (Bauchgefühl) nicht mit der Größe gerechnet. Zum Thema Statistik:
Delphi-Quellcode:
... bedeutet ja, daß reichlich Platz verschwendet wird. Die Inserts laufen als Block wie hier empfohlen
T_RECORD_DATA (153)
Primary pointer page: 150, Index root page: 172 Data pages: 82929, data page slots: 82929, average fill: 63% Fill distribution: 0 - 19% = 0 20 - 39% = 1 40 - 59% = 0 60 - 79% = 82928 80 - 99% = 0 Index FK_T_RECORD_DATA_1 (0) Depth: 3, leaf buckets: 8073, nodes: 21680580 Average data length: 0.00, total dup: 21679353, max dup: 19155 Fill distribution: 0 - 19% = 1 20 - 39% = 0 40 - 59% = 2451 60 - 79% = 0 80 - 99% = 5621 Index T_RECORD_DATA_IDX1 (2) Depth: 3, leaf buckets: 7010, nodes: 21680580 Average data length: 0.06, total dup: 20624315, max dup: 87 Fill distribution: 0 - 19% = 0 20 - 39% = 0 40 - 59% = 1 60 - 79% = 0 80 - 99% = 7009 ![]()
Delphi-Quellcode:
Alle Blöcke laufen in einer Transaktion. Wo läßt sich da noch was rausholen.
execute block as begin //25Kb je Block
insert into T_RECORD_DATA... // 200x je Block. Änderung der Menge machte keinen Unterschied. end Zitat:
|
AW: Firebird Datenbankgröße
Vielleicht kannst Du Deine Speicherung auch der auf dem Gerät angleichen. Wenn ich mir die Struktur aus dem OP ansehe, habe ich da so Vermutungen:
Nachteil wäre die Rechnerei die Du beim Auswerten hättest. Immer das Selbe: Platzersparnis <> Performance. |
AW: Firebird Datenbankgröße
Ist das mit dem Platz im Jahr 2014 wirklich ein Problem?
|
AW: Firebird Datenbankgröße
Zitat:
Übersehen nicht, nur nicht explizit drauf eingegangen. Aufgrund der Beschreibung bin ich davon ausgegangen, dass die Daten einmal importiert werden um dann für Auswertungen vorgehalten werden bzw. bei Aktualisierungen die Daten als "Masseninserts" rein kommen und nicht individuell von den Anwendern geändert werden können / sollen. Und hier würde ich (wenn die DB-Größe wirklich ein Thema sein sollte) ggf. die beschrieben Dinge anwenden. Unter 2.5 soll es ja auch möglich sein über StoredProcedures auf anderen DBs zugreifen zu können. Somit könnten diese Gerätedaten in eigene, ggf. auch als Read-OnlyDBs ausgelagert werden und die Pages voll gemacht werden. Aber hier müsste der Threadstarter vielleicht noch Licht ins Dunkel bringen... |
AW: Firebird Datenbankgröße
Zitat:
Leider ist das Denken "wieso Performance? Ich hab unendlich viel Speicher und Dutzende von Prozessorkernen." genau so weit verbreitet wie die Verwechselung einer IDE mit einem Point-And-Click-Adventure. |
AW: Firebird Datenbankgröße
Danke an Alle...:thumb:
@Union: interessante Ansätze. Zitat:
Zitat:
Im Beispiel: letzter DS = 1398999942 erster = 1381299573 Zitat:
Zitat:
PS: Es geht um Temperaturaufzeichnungen in der Lebensmittelbranche und Pharmaciebranche. Die genauen Speicherzeiträumen per Gesetzt sind mir unbekannt. Da aber das Finanzamt 10 Jahre Aufbewahrung hat ging ich mal ebenso davon aus. Rein theoretisch hat das Gerät einen Speicherzyklus von 1-3 Jahren je nach Auflösung. Dann werden die ersten Daten wieder überschrieben. Per Gesetz sind die so zugelassen und man könnte die DB Speicherung auch darauf begrenzen. Ich will aber einen Mehrwert für den Kunden. Quasi das was die Hardware nicht leistet. Zitat:
|
AW: Firebird Datenbankgröße
Zitat:
Das man Fehler speziell am Anfang vermeiden soll, ist mir auch klar, nur baut man manchmal eben auch am Anfang Fehler ein. Und wenn man schon überlegt, mit sparse-array Techniken hier Platz zu sparen, dachte ich mir, ich hebe mal einen Zeigefinger. Wir leben im Jahr 2014, wo Festplattenspeicherplatz in Tera- und Petabytes gemessen wird. Wir sollten uns nicht darüber über Gebühr Gedanken machen, eine Datenbank von 1.6GB auf vielleicht 800GB zu komprimieren. Da spart man an Festplatten eigentlich kaum was (ok, sagen wir: alle 500 Jahre eine TB-Platte, oder bei 500 Geräten 1x pro Jahr 1 TB). Wenn es ein Bug oder eine Fehleinstellung ist: Ja, natürlich muss man das in Ordnung bringen. Wenn ich signifikant Geld spare, auch ok. Aber das muss man immer wieder neu überlegen. Ich persönlich würde mich hüten, hier zu viel Energie hineinzustecken. |
AW: Firebird Datenbankgröße
Zitat:
Zitat:
Zitat:
aber wieso dann 10 Stellen? wäre es da nicht vllt. besser ein Char (0,1,A..z..) und ein float-Feld zu nutzen? (ich kenn die FB-Typen nicht sooo genau) Noch ein Nachsatz zum Platzsparen. es ist Blödsinn Informationen so zu verstümmeln, daß sie u.U. wertlos werden - die Erhöhung eines Basidatums gehört für mich dazu. Aber die Einstellung Festplattenkapazität mißt sich in TByte da kann ich auch mal ein paar GByte über die Leitung schicken baut beim Anwender gewaltig Frust auf wenn er, weil sein Netzanschluß unterdimensioniert ist, wieder einmal 2 Minuten auf eine Antwort/Sendung warten darf. (nichts für ungut, aber heute war unser Firmennetz wieder vollkommen zu ...) Gruß K-H Gruß K-H |
AW: Firebird Datenbankgröße
Zitat:
Wenn also die Messdaten wirklich nur abgelegt werden sollen, ist eine Einzelspeicherung u.U. auch ein Overkill. Du könntest die Daten einfach in ein 'Array Of TRecord' ablegen und z.B. jeweils Arrays a 1000 Werte mit Zeitstempel ablegen. Ist zwar ziemlich bescheuert, aber mit SQL willst Du an die Einzeldaten dann ja eh nicht. Man kann auch zippen, um Redundanzen herauszuziehen und so z.B. eine ganze Stunde Messdaten eines temperierten Raumes (da ändert sich dann nicht viel) ziemlich platzsparend unterbringen. Die Daten sind in einem BLOB und der ist in einer separaten Datei und bis auf den Header in der Tabelle ist alles andere dynamisch. |
AW: Firebird Datenbankgröße
Liste der Anhänge anzeigen (Anzahl: 1)
Gut, ich drösel das mal auf: :P
1 Gerät, 1-100 Devices(Busadressen) im 485er Bus. Jedes Device hat unterschiedliche Parameter (F_PARAMETER_ID) (Anzahl und Typ) welche von mir vor dem Datenabholen eine eindeutige ID bekommen. Diese wird dann in den RecordDaten den Bezug zum Gerät/Adresse herstellen. Im Schnitt hat jedes Device(Busadresse) 13 Parameter, mal mehr mal weniger. Jeder Parameter kann entweder einen String (*, +), einen Index (0-4), einen Boolean (0,1) oder einen Float Wert (-999.99 - 999.99) haben. Deshalb die Speicherung als Char was alles abdeckt. Beispiel: Bild 1 Zitat:
Zitat:
Zitat:
damit ergeben sich pro Minute 100 Adressen * 13 Parameter * 4 = 5200 Datensätze/ Meßwerte Zitat:
|
AW: Firebird Datenbankgröße
Firebird verwendet eine RLE Komprimierung mit einem Byte für die Länge, es ist also für den Speicherbedarf egal ob das Feld als
Varchar(10) oder Varchar(100) definiert wird, wenn es meist weniger sind wie 8 Char im Varchar das Varchar hat ein Integer(?16Bit?) als Länge das Varchar(10) belegt also maximal 12 Byte (Single Byte Charset vorrausgesetzt) Auf der anderen Seite hat ein CHAR Feld immer nur die angegebene Länge also Char(10) hat eine Länge von 10 wird aber mit Spaces gepadded zu beachten ist hier natuerlich auch der definierte Zeichensatz |
AW: Firebird Datenbankgröße
zum vor und nachteil von char oder varchar bei Firebird:
Beim Speichern braucht Firebird für ein varchar mit gleichem Inhalt 2 Byte mehr als wenn es in einem Char gleicher maximallänge gespeichert wäre. Darin speichert Firebird die Datenlänge. Bei x Millionen Records also schon ein Vorteil, wenn man den char nimmt, der braucht diese beiden Bytes nicht. Abgesehen von den beiden Längenbytes speichert Firebird Inhalte von char und varchar in gleicher Länge, d.h. nahezu immer die reinen benutzten bytes plus ein wenig Overhead (lange chars/varchars mal ausgenommen). Leider kein Vorteil ohne Nachteil, denn während varchars im Netzwerk als reine Nutzdaten + overhead übertragen werden, werden chars mit Leerzeichen aufgefüllt, leider auch + overhead. Bei den Beispieldaten hier sind das mit 3 Records 20 Byte (188 zu 168 Byte) weniger, also ca. 10 % weniger netzwerktraffic, wenn man den varchar nimmt. Da das Netzwerk meistens wesentlich langsamer ist als der Zugriff auf die Festplatte bzw der bereits im Ram gecachten Daten, ist bei netzwerkintensiven Programmen meistens der varchar vorteilhaft, bei archivierten Daten, die selten abgefragt werden oder wirklich festen Längen aber manchmal eben auch der char. Dann bringt es dann ggf. wesentlich mehr, die von dir beschriebenen Varianten der Messwerte über Nachschlagetabellen mit einem 4 Byte integer als Foreign Key zu verbinden, wenn man schon um jedes Byte kämpfen will. Datenpaket mit varchar
Code:
CREATE TABLE T1 ( ID BIGINT NOT NULL, TXT VARCHAR(20) ); Daten ID TXT 1 ABC 2 ABCDEF 3 ABCDEFGHIJKLMNOP SQL select * from T1 Netzwerkprotokoll Ausschnitt mit tcpipexpert erstellt ## 12:06:16:597 Channel 2; DATA (Server -> Client): Length= 168 00 00 00 09 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 42 00 00 00 00 00 00 00 01 00 00 00 00 B 00 00 00 01 00 00 00 00 00 00 00 03 41 42 43 00 ABC 00 00 00 00 00 00 00 42 00 00 00 00 00 00 00 01 B 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 06 41 42 43 44 45 46 00 00 00 00 00 00 00 00 00 42 ABCDEF B 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 10 41 42 43 44 45 46 47 48 ABCDEFGH 49 4A 4B 4C 4D 4E 4F 50 00 00 00 00 00 00 00 42 IJKLMNOP B 00 00 00 64 00 00 00 00 d Datenpaket mit char
Code:
CREATE TABLE T2 (
ID BIGINT NOT NULL, TXT CHAR(20) ); ID TXT 1 ABC 2 ABCDEF 3 ABCDEFGHIJKLMNOP SQL select * from T2 Netzwerkprotokoll Ausschnitt mit tcpipexpert erstellt 12:06:29:002 Channel 2; DATA (Server -> Client): Length= 188 00 00 00 09 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 42 00 00 00 00 00 00 00 01 00 00 00 00 B 00 00 00 01 00 00 00 00 41 42 43 20 20 20 20 20 ABC 20 20 20 20 20 20 20 20 20 20 20 20 00 00 00 00 00 00 00 42 00 00 00 00 00 00 00 01 00 00 00 00 B 00 00 00 02 00 00 00 00 41 42 43 44 45 46 20 20 ABCDEF 20 20 20 20 20 20 20 20 20 20 20 20 00 00 00 00 00 00 00 42 00 00 00 00 00 00 00 01 00 00 00 00 B 00 00 00 03 00 00 00 00 41 42 43 44 45 46 47 48 ABCDEFGH 49 4A 4B 4C 4D 4E 4F 50 20 20 20 20 00 00 00 00 IJKLMNOP 00 00 00 42 00 00 00 64 00 00 00 00 B d |
AW: Firebird Datenbankgröße
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:19 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 by Thomas Breitkreuz