Teilzugriff auf BLOB Felder

Themen rund um den praktischen Einsatz von Firebird. Fragen zu SQL, Performance, Datenbankstrukturen, etc.

Moderator: thorben.braun

Groffy
Beiträge: 35
Registriert: Do 12. Apr 2018, 23:14

Hallo Zusammen,

wie ich schon in einem anderen Zusammenhang beschrieben hatte, werden in der Anwendung die ich betreue, Messdaten binär in BLOB Feldern gespeichert. Das hat auch bislang zufriedenstellend geklappt, da die Größe der Messdaten sich im Bereich 2-10Mb bewegt haben. Nun wird als Sensor eine Zeilenkamera angeschlossen und die Größe der Datensätze bewegt sich zwischen 200-500Mb was zu Geschwindigkeitsproblemen im Schreiben und Lesen der Datensätze bringt - es dauert. Beim schreiben gibt es wenig Alternativen, aber beim lesen habe ich mir überlegt die Binärdaten evtl. blockweise auszulesen. Gibt es da Möglichkeiten BLOBs nur teilweise auszulesen? Also eine Art von SUBSTRING(von bis) für Binärdaten?



Beste Grüße - Ulrich
Benutzeravatar
martin.koeditz
Beiträge: 315
Registriert: Sa 31. Mär 2018, 14:35

Hallo Ulrich,

ob es da was gibt? Eventuell lohnt sich der Blick in die Dokumentation von JayBird, dem JDBC-Treiber. Dort gibt es die Funktion getBinaryStream(). Eventuell lassen sich hier Paketgrößen oder ähnliches einstellen.

Gruß
Martin
Martin Köditz
it & synergy GmbH
bfuerchau
Beiträge: 290
Registriert: Mo 7. Mai 2018, 18:09

Ich würde mir da auf jeden Fall Gedanken machen, ob dein Design dafür noch ausreicht.
Blobs sind gut für Dokumente aber nicht für Daten.
Wenn man sich überlegt, dass man bei kurzen Datensätzen (also wenige Felder) bis zu 3000 oder auch mehr Inserts per Sekunde erreicht, weiß ich ehrlich nicht, warum du das mit den Blobs eingeführt hast.
Jetzt rächt sich das Konzept.
Eine Substring-Funktion wird dir da auch nicht viel bringen, da ja auch Blobs komprimniert in die DB geschrieben werden. Man muss also sowieso den Blob komplett auslesen und dekomprimieren um den Substring durchzuführen. Performamcemäßig die reinste Katastrophe.
Auch auswertungstechnisch sehe ich da grundsätzlich schwarz, da du viele SQL-Funktionen schlicht nicht nutzen kannst.
Benutzeravatar
martin.koeditz
Beiträge: 315
Registriert: Sa 31. Mär 2018, 14:35

Hallo Urlich,

wie bfuerchau bereits geschrieben hat, ist ein Redesign vielleicht angebracht. Ob das machbar ist, hängt natürlich von deiner Anwendung ab.

Gruß
Martin
Martin Köditz
it & synergy GmbH
Groffy
Beiträge: 35
Registriert: Do 12. Apr 2018, 23:14

Hallo Martin, bfuerchau,

in der Tat scheint das Speicherkonzept an seine Grenzen gestoßen zu sein, was die Speicherung eines Messdatensatzes in ein einzelnes BLOB Feld angeht. Gestern Nachmittag ist mir dann auch die Idee gekommen, die Messdatensätze in Blöcke aufzuteilen.

Danke euch Beiden fürs mitdenken, ich werde hier berichten wie erfolgreich die Umsetzung war.

Gruß Ulrich
bfuerchau
Beiträge: 290
Registriert: Mo 7. Mai 2018, 18:09

Wie gesagt, ich würde da auch keine Blöcke speichern, denn für Auswertungen ist das absolut unbrauchbar.
Ich glaube auch nicht, dass du mehrere 100 Messdaten/Sekunde bekommst.
Benutzeravatar
martin.koeditz
Beiträge: 315
Registriert: Sa 31. Mär 2018, 14:35

Hallo Urlich,

spricht etwas dagegen, die Messdaten in ein einfaches Schlüssel-Wert-Muster zu bringen? Oder hast du die Blöcke damit gemeint?

Gruß
Martin
Martin Köditz
it & synergy GmbH
Groffy
Beiträge: 35
Registriert: Do 12. Apr 2018, 23:14

Guten Morgen Martin,

möglich wäre das, aber es würde einfach eine riesige Menge von Datensätzen generieren. Als Beispiel Messdaten mit denen ich gerade teste :

10k x 10k Messpunkte = 100Mio Punkte. Typischerweise liefern die Sensoren einen Intensitätskanal (short = 16bit) , einen Höhenkanal (float = 32Bit), und eine sogenannte Maske (byte) die angibt ob Messpunkte als "gültig" gelten.

Wenn ich die Messdaten in BLOB Felder speichere, dauert schreiben ca. 8-10 Sekunden/lesen ca. 20 Sekunden. Was ich gestern implementiert und getestet habe, war das zeilenweise Lesen und Schreiben in Datenblöcken, also immer 10k Datenpunkte pro Datenbankzeile. Das macht das ganze zwar noch langsamer (30-40 Sekunden), aber etwas geschmeidiger, weil ich die Möglichkeit habe Lese/Schreib Fortschritte in der GUI anzeigen zu können. Aber alles in allem : es macht keinen Spaß.

Also - Umstellung auf dateibasierte Datenspeicherung : lesen/schreiben ca. 0.6-0.8 Sekunden mit einer SSD.

Der Aufwand die Datenintegrität zu waren hält sich momentan in Grenzen. Momentan ist es als Option schaltbar, wo die Messdaten abgelegt werden. Falls Netzwerkzugriff benötigt wird, und die Größe der Messdaten handlich genug ist, bleibt es vorerst bei der Speicherung in der Datentabelle. Das Ganze geht jetzt erst einmal in den Testbetrieb.


Gruß Ulrich
vr2
Beiträge: 120
Registriert: Fr 13. Apr 2018, 00:13

Hallo Ulrich,

vielleicht diese Idee noch dazu: Wenn ichs richtig sehe, bestehen Deine Messpunkte aus 7 Bytes. Die könntest Du in einen bigint kodieren und dann mit bit-und byte-Funktionen bin_and, bin_shl, bin_shr usw drauflosgehen, um die Bestandteile auszuwerten. Die Bit-/Bytefunktionen sind naturgemäß sehr schnell, schneller kriegst Du die Bestandteile nicht extrahiert.

Von solchen Messpunkt-Bigints könntest Du in einer Tabelle 10 Spalten definieren, oder 100, müsstest Du ausprobieren, was in Deinem Fall besser performt und handlicher ist. Selbst eine Messpunkttabelle der Breite 100 Bigints hätte nur eine Satzbreite von 800 Bytes, was noch relativ wenig ist. Damit müsstest Du mit einer halbwegs brauchbaren CPU (was die single-thread-Performance angeht, falls Du hier nicht parallelisieren und mehrere Clients gleichzeitig schreiben lassen kannst) auf eine insert-Performance von ca 200K Sätzen / sek kommen. Bei der 100 Spalten breiten Tabelle wären das für 100 Mio Messpunkte also 5 Sek Schreiben plus etwas Umformungsoverhead.

Falls Du den Input parallelisieren kannst, also in separate Happen organisiert kriegst, wäre das auch noch eine Fährte zur Optimierung. Tests, die ich bzgl Parallelisierung mal gemacht habe, zeigten, dass Du damit nochmal Faktor 3-4 rausholen kannst, das skaliert nicht unbegrenzt. Im besten Fall erreichst Du vieleicht 1-2 Sek, mit sämtlichen Optimierungen. Das Problem ist da hauptsächlich das bulk load der Daten. Das Auswerten geht dann aber wegen Basistyp Bigint und bin_*-Funktionen deutlich schneller als bei den Blobs.

Ansonsten, wenn Deine Messreihen noch deutlich größer werden und maximale Schreib-Lese-Auswertungsperfomance gefragt ist, wäre evtl eher ein R-Server angebracht. Der ist dafür optimiert und hat nicht den transaktionalen Overhead.

Viele Grüße, Volker
Groffy
Beiträge: 35
Registriert: Do 12. Apr 2018, 23:14

Hallo Volker,

vielen Dank für diesen interessanten Ansatz. Ich werde damit mal ein wenig experiementieren.


Beste Grüße Ulrich
Antworten