Zur Hauptseite ... Zum Onlinearchiv ... Zum Abonnement ... Zum Newsletter ... Zu den Tools ... Zum Impressum ... Zum Login ...

Achtung: Dies ist nicht der vollständige Artikel, sondern nur ein paar Seiten davon. Wenn Sie hier nicht erfahren, was Sie wissen möchten, finden Sie am Ende Informationen darüber, wie Sie den ganzen Artikel lesen können.

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

E-Mail:

Gedrucktes Heft

Diesen Beitrag finden Sie in Ausgabe 3/2007.

Unser Angebot für Sie!

Lesen Sie diesen Beitrag und 500 andere sofort im Onlinearchiv, und erhalten Sie alle zwei Monate brandheißes Access-Know-how auf 72 gedruckten Seiten! Plus attraktive Präsente, zum Beispiel das bald erscheinende Buch 'Access 2010 - Das Grundlagenbuch für Entwickler'!

Diesen Beitrag twittern

Zusammenfassung

Erfahren Sie, wie Sie Dateien oder lange Texte auf platzsparende Weise in Tabellenfeldern speichern können.

Techniken

VBA, API-Programmierung, Formulare

Voraussetzungen

Access 2000 und höher

Beispieldateien

Binaer.mdb; binaer.accdb

Shortlink

466

Komprimierte Binärspeicherung

Sascha Trowitzsch, Berlin

Dateien oder andere Binärobjekte in Datenbanktabellen zu speichern, ist bei vielen Access-Entwicklern verpönt. Das Hauptargument, das man dabei zu hören bekommt, ist das unverhältnismäßige Aufblähen der Datenbanken. Das greift jedoch nur dann, wenn die Objekte in einem OLE-Feld als OLE-Objekte abgespeichert werden. Denn dabei findet eine Konversion der Quelldateien in OLE-kompatible Dokumentenformate statt, die sie vergrößern. Dabei lassen sich die Dateien mit wirklich binärer Speicherung als BLOBs durchaus Platz sparend unterbringen – vor allem, wenn man sie dann noch zusätzlich mit einer Komprimierung versieht. Im folgenden Beitrag werden einige Anwendungsbeispiele und die zugrunde liegenden Techniken beleuchtet.

Wozu Binärobjekte?

Das sicher am häufigsten nachgefragte Feature für Binärobjekte in Datenbanken ist die Anzeige von Bildern. Das ist auch nachvollziehbar, denn Entitäten in Datenbanken sind mit wahren Objekten der Realität verknüpft, die nun mal eine visuelle Entsprechung haben.

Ein Kunde hat ein Gesicht, ein Produkt ein Aussehen, eine Firma ein Logo. Das Konterfei eines Kunden also dem entsprechenden Kundendatensatz zuzuordnen, ein Produktbild ins Warenwirtschaftssystem zu bringen oder im Lieferantenformular Logos zu platzieren, macht durchaus Sinn.

Interessant wäre aber auch, etwa die Korrespondenz mit einem Kunden in Form von Texten, Word-Dokumenten, PDFs oder Excel-Dateien mit in eine Datenbank aufzunehmen, damit man direkt aus dem Kundenformular schnell darauf zugreifen kann.

Üblicherweise speichert man in der Datenbank lediglich Verweise auf das Dateisystem und öffnet die Dateien zur Laufzeit mit der entsprechenden Anwendung. Das ist tatsächlich empfehlenswert, solange man sicher sein kann, dass sich Pfade nicht ändern, Dateien nicht verschoben werden und jeder Anwender überhaupt Zugriff auf die Verzeichnisse im Netzwerk hat.

Tritt einer dieser Fälle ein, dann ist man mit der Schwierigkeit konfrontiert, die Pfade in der Datenbank upzudaten oder Berechtigungen neu zu vergeben.

Das alles wäre überflüssig, wenn sich die Dateien gleich innerhalb der Datenbank befänden.

Wie kann man Binärdaten speichern?

Es gibt je nach Access-Version bis zu drei übliche Möglichkeiten der Binärspeicherung, denen dieser Beitrag noch eine weitere hinzufügt - die Speicherung komprimierter Daten:

  • OLE-Objekte
  • BLOBs
  • Komprimierte BLOBs
  • Anlagen (Access 2007)

Ole-Felder sind für die erstgenannten drei Möglichkeiten der zu verwendende Datentyp des Binär-Containers. In Access 2007 wurde zusätzlich der neue Typ Attachment (Anlagefeld) eingeführt.

OLE-Objekte

OLE-Objekte sind sehr leicht zu handhaben, weil Access sich dabei sowohl um die Speicherung wie auch die Anzeige der Dateien kümmert. Sie lassen sich direkt in der Datenblattansicht in OLE-Feldern speichern und durch einfachen Doppelklick öffnen. Das Speichern geschieht etwa über den Eintrag Objekt einfügen... des Kontextmenüs eines leeren OLE-Felds. Im anschließend erscheinenden Dialog aktiviert man Aus Datei erstellen, wählt die Datei über den Durchsuchen-Button aus und deaktiviert außerdem das Kontrollkästchen Verknüpfen.

Bei dieser Vorgehensweise wird die Datei in jedem Fall in ein OLE-kompatibles Format konvertiert. Das bedeutet, dass sie mit Informationen zu einem auf dem Rechner verknüpften OLE-Server versehen wird. Ist dem Dateityp im System kein OLE-Server – das ist ein OLE-automationsfähiges Programm – zugeordnet, so wird ein Paket erstellt. Das ist ebenfalls ein OLE-Format – quasi ein Wrapper, ein Container für eine Datei. Beim Doppelklick wird diese Datei temporär wiederhergestellt und mit der verknüpften Anwendung geöffnet.

Bei einer dezidiert mit einem OLE-Server verknüpften Datei muss hingegen genau dieser OLE-Server auch auf dem Zielrechner installiert sein, wenn man der Fehlermeldung OLE-Server ist nicht vorhanden oder konnte nicht gefunden werden entgehen will. Speichert man etwa ein Word-Dokument in das OLE-Feld, dann muss auf dem Zielrechner ebenfalls Word installiert sein, wenn die Datei wieder aufgerufen werden soll. Würde das Dokument hingegen als Paket gespeichert, dann käme gegebenenfalls auch Wordpad zum Öffnen in Betracht.

Man kann hier schon das wichtigste Problem im Zusammenhang mit OLE-Objekten ablesen: Ohne passenden OLE-Server keine Anzeige der Datei. Gerade bei Bilddateien kommt es häufig vor, dass diese über den OLE-Server Microsoft Photo Editor gespeichert werden, der aber auf einem Zielrechner nicht vorhanden ist. Ein JPG etwa kann selbst dann nicht geöffnet werden, wenn andere taugliche Bildanzeigen installiert sind.

Hinzu kommt, dass eine Datei als OLE-Objekt im OLE-Server in ein für ihn schnell lesbares Format umgewandelt und auch so abgespeichert wird. Ein JPG wird etwa häufig in ein bitmap-ähnliches Format konvertiert, das weitaus größer ist als die Ursprungsdatei. So kommt das Aufblähen der Datenbank zustande.

BLOBs

Beim Speichern als BLOBs (Binary Large Objects) hat man solche Probleme nicht. Hierbei wird die Datei Byte für Byte identisch mit dem Original im OLE-Feld gespeichert, dessen Kennzeichnung somit nicht mehr korrekt ist, weil es nun mit OLE überhaupt nichts mehr zu tun hat. Richtiger wäre die Bezeichnung LongVarBinary, wie sie ähnlich auch in SQL verwendet wird. Bei dieser Methode wächst die Datenbank entsprechend der Größe der eingelesenen Datei. Nachteil: Das Speichern und Auslesen muss per VBA-Routinen erfolgen, weil die Oberfläche von Access keine entsprechenden Mittel zur Verfügung stellt.

Komprimierte BLOBs

Das Speichern als komprimiertes BLOB funktioniert in gleicher Weise, nur mit dem Unterschied, dass die Datei zuvor mit geeigneten Algorithmen komprimiert wird. Dieses Komprimieren könnte man bereits im Dateisystem vollziehen, indem man die Datei zunächst mit einer Zip-Anwendung in eine Archiv-Datei konvertiert und erst dann einliest. Das ist jedoch überflüssig, weil es Möglichkeiten gibt, die Kompression rein im Speicher durchzuführen. In diesem Beitrag wird von solchen Möglichkeiten Gebrauch gemacht, wobei die Open-Source-Komponente zlib zum Einsatz kommt.

Tab. 1 zeigt den Speicherbedarf für die unterschiedlichen Methoden.

Beispieldatei

Größe

OLE-Objekt

BLOB

Komprimiertes BLOB

PDF

65 kB

3112 kB

69 kB

53 kB

TIF (Screenshot)

837 kB

843 kB (Paket)

843 kB

21 kB

Summe

902 kB

3995 kB

912 kB

74 kB

Tabelle 1: Speicherbedarf realistischer Beispieldaten bei unterschiedlichen Verfahren

Für welches der drei Verfahren man sich hiernach entscheidet, ist wohl klar: OLE-Speicherung vergrößert die Datenbank gegenüber komprimierter BLOB-Speicherung für die hier verwendeten Formate um den Faktor 54!

Solche Erfahrungen hat Microsoft dann wohl auch mit dazu bewegt, in Access 2007 den neuen Feldtyp Anlage (Attachment) einzuführen, dem ebenfalls eine komprimierte BLOB-Speicherung zu eigen ist. In Attachments können Sie Dateien mit dem gleichen Komfort über die Oberfläche speichern wie bisher in OLE-Feldern. Sie werden dabei aber nicht verändert, brauchen keinen OLE-Server und werden automatisch immer dann komprimiert, wenn es sinnvoll ist, also eine nennenswerte Verkleinerung der Daten zu erwarten ist. Das geschieht alles hinter den Kulissen.

Es stellt sich also die Frage: Ist mit Access 2007 das Thema erledigt? Nach den Erfahrungen des Autors: Nicht ganz! Zum einen ist die Performance beim Ein- und Auslesen von Attachments deutlich geringer als das Gespann von BLOBs und ZLIB – etwa um den Faktor 1,5 –, zum anderen ist die Dateigröße etwas limitiert. Offenbar benötigt Access 2007 beim Einlesen von Dateien etwa gut das Doppelte der Dateigröße an RAM – den einen Teil für die Datei selbst, den anderen für das Ergebnis der Komprimierung.

So war es auf einem Rechner mit 700 MB freiem physischem RAM nicht möglich, Dateien größer als 220 MB in ein Anlagefeld zu speichern. Nicht, dass so große Dateien überhaupt in Datenbanken gespeichert werden sollten, aber bereits weit unter dieser Größe ließ die Performance erheblich zu wünschen übrig. Attachments kommen daher eher für kleinere Dateien in Betracht.

Ein anderer Punkt ist, dass es noch kaum Erfahrungen mit einer größeren Anzahl von Attachments in Access 2007-Datenbanken gibt und es nicht als sicher gelten kann, ob sich hier nicht die Probleme in puncto Stabilität wiederholen könnten, die es auch schon etwa mit Memofeldern gab.

BLOBS speichern

Binärdaten können über die Datenzugriffsbibliotheken DAO oder ADO in Tabellen gespeichert werden. DAO erwartet dabei zunächst ein Byte-Array als Zwischenspeicher für die Dateien, gefolgt von der Methode Field.AppendChunk, während ADO seit Version 2.5 ein Stream-Objekt mit der Methode LoadFromFile kennt, dessen Inhalt anschließend per Stream.Read einem Feldinhalt zugewiesen werden kann.

Das sieht einfacher aus und ist es auch, geht aber leider langsamer vonstatten als die DAO-Methode, sodass es keinen Grund gibt, hier ADO einzusetzen – außer Sie arbeiten mit Access-Projekten (ADP), in denen DAO nicht verwendet werden kann. Sie finden beide Verfahren im Modul mdlBLOBs der Beispieldatenbank binaer.mdb.

Die Routine aus Listing 1 verdeutlicht das Prinzip. Sie lädt eine Datei in ein Byte-Array und speichert dessen Inhalt anschließend in einem Tabellenfeld, das als OLE-Objekt definiert wurde.

Listing 1: Datei per DAO in ein Tabellenfeld einlesen

Sub SpeichereDatei()

     Dim bin() As Byte

     Dim rst As DAO.Recordset

     Open “c:\dateiname.dat” For Binary Access Read As #1

     ReDim bin(LOF(1))

     Get #1, , bin

     Close #1

     Set rst = CurrentDb.OpenRecordset(“Tabelle1”, dbOpenDynaset)

     rst.AddNew

     rst!Binaerfeld.AppendChunk bin()

     rst.Update

     rst.Close

End Sub

Sie haben das Ende des frei verfügbaren Teils des Artikels erreicht. Lesen Sie weiter, um zu erfahren, wie Sie den vollständigen Artikel lesen und auf viele hundert weitere Artikel zugreifen können.

Sind Sie Abonnent?Jetzt einloggen ...
 

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

E-Mail:

© 2003-2015 André Minhorst Alle Rechte vorbehalten.