Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Datenbank zur Ablage von (mitunter großen) Blob flieds? (https://www.delphipraxis.net/133127-datenbank-zur-ablage-von-mitunter-grossen-blob-flieds.html)

moelski 26. Apr 2009 07:01

Datenbank: N/A • Version: N/A • Zugriff über: N/A

Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Moin !

Da es ja offenbar mit der AbsoluteDB nicht funktioniert (http://www.delphipraxis.net/internal...t.php?t=156012) würde ichgernemal nachfragen ob da jemand was anderes empfehlen kann.

Wir haben eine MDI Anwendung wo jedes MDI Fenster ein TChart oder RichEdit ist. Den Inhalt der jeweiligen MDI Fenster würden wir gerne als Stream in einem Blob Feld in der Datenbank ablegen. Daneben müssen zu jedem Blob noch eine Menge anderer Infos abgelegt werden wie z.B. Erstellzeit, -datum, Beschreibung, ....
Aber das sind alles recht überschaubare Datenmengen. Das Problem sind die Streams die mitunter doch recht groß werden können (Bei einem RichEdit mit Bildern locker mal in Richtung 100MB).

Folgendes müsste die Datenbank "erledigen":
* Wenn ein MDI Fenster geschlossen wird, die Daten (Stream) in das zugehörige Blob Feld schreiben.
* Die Daten sind bei uns in einem TreeView strukturiert. Wenn der User ein Element im Tree anklickt wird das MDI Fenster (wenn nicht vorhanden) neu generiert und dann die Daten aus dem Blob zurück geladen.

Im Grunde ist das schon alles. ABER ... Da unsere Anwendung nun mal auf MDI basiert kann ein User zig Fenster auf einen Schlag schließen oder auch öffnen. Bedeutet das Laden der Daten aus der DB und in die DB sollte mittels Thread erfolgen. Bis hierhin konnte das die DB ja. Allerdings hat die AbsoluteDB bei großen Datenmengen die Tabelle gelockt. Und wenn man dann auf andere Datensätze zugreifen wollte ging nix mehr (Anwendung hängt).

Ach ja und die Datenbank sollte folgendes Unterstützen:
* Datenbank ist single File orientiert
* Tool um die Datenbank Datei auch ohne die eigentliche Anwendung öffnen / bearbeiten zu können
* keine extra Installationen für die Datenbank. Das verkraften unsere User nicht :) Also entweder so wie Abolute DB in die Anwendung integriert oder über externe DLLs die man direkt mit der Anwendung installieren kann.
* Lizenz sollte auch für kommerzielle Nutzung geeignet sein.

Kann da jemand was zu empfehlen?

mjustin 26. Apr 2009 07:15

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Für Single-User-Betrieb: Embedded Firebird. Eine Embedded InterBase Version (InterBase 2009 ToGo, unter 3 Megabyte) scheint es auch zu geben. Dabei läuft kein separater Datenbank-Server-Prozess, die Datenbank-Engine wird in dem Prozessraum der Anwendung ausgeführt. Ich habe sie aber noch nicht getestet.

Pfoto 26. Apr 2009 07:44

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Hallo Dominik,

Auch wenn NexusDB jede Tabelle als separate Datei angelegt, nenne
ich das System mal hier, da es von der Geschwindigkeit und dem
SQL-Sprachumfang her sehr weit vorne liegt.
Der Zugriff kann auch ohne Probleme aus mehreren Threads heraus erfolgen.
Ich hatte mich für NexusDB entschieden, nachdem ich zuvor übrigens
AbsoluteDB und AccuRacer getestet hatte - die schnitten bei den
gleichen (großen) Datenmengen oft deutlich langsamer ab.

P.S. Ich weiß ja nicht, wie lange das Schreiben des Blobs dauert,
aber könnte man in der Zeit nicht ein Progressbar-Fenster zeigen, das
es für diese Zeit unmöglich macht, weitere Fenster zu schließen?
Zumindest wäre das doch in der Übergangszeit bis zur Implementierung
einer neuen DB sinnvoll.

Gruß
Jürgen

moelski 26. Apr 2009 08:37

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Moin !

NexusDB hatte ich mir auch schon mal angesehen. Allerdings finde ich da die Preise recht gesalzen ...
Und auf den ersten Blick ist mir auch nicht ersichtlich was ich für unser Vorhaben dort kaufen müsste.

Zitat:

Ich weiß ja nicht, wie lange das Schreiben des Blobs dauert,
aber könnte man in der Zeit nicht ein Progressbar-Fenster zeigen
Ja das ginge sicherlich. Allerdings darf auch keinen Fall der Main Thread hängen. Denn dann würden eingehende Daten verloren gehen was ungünstig wäre.
Hmm ich muss das mal testen ob das mit dem "Sperren" so geht. Das könnte in der Tat eine Lösung sein. Denn im Normalfall dauert das Speichern nicht soo lange.

Greetz Dominik

ConstantGardener 26. Apr 2009 08:48

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Hallo Moelski,

bei NexusDb ist die EmbeddedVersion ohne Source free. Mit Source 100 Aut$. Ich denke das ist mehr als ok. Für die Server wird per Entwickler abgerechnen (750 Aut$). Der AWE Server ist teurer und wird per Maschine abgerechnet. Den brauchst Du aber denke ich nicht.
Das waren die Preise bis V2. Die V3 kommt ja demnächst. Evtl. ändert sich dort dann was.

cg

moelski 26. Apr 2009 09:00

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Moin !

Nu die Embedded wäre ja genau was wir brauchen.
Und die kann auch Multi Thread ohne Table Lock?
Was mich dann aber dennoch etwas stört sind die Dateien pro Tabelle:
Zitat:

jede Tabelle als separate Datei angelegt
Geht das nicht in einer Datei ?

ConstantGardener 26. Apr 2009 09:19

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Hallo moelski,

ob Multithread in der der Form unterstützt wird kann ich auch nicht sagen. Schau am besten mal im Forum von NexusDB vorbei. Die Speicherung geschieht immer in einzelnen Dateien. Das hat natürlich Vor- und Nachteile. Wird nutzen eine Zip-Kompo um alle Datendateien, INIs, JPGs usw. in einer Datei zusammenzupacken um dem Nutzer das Handling zu erleichtern (Mandantenfähigkeit light sozusagen). Das Datenverzeichnis wird einmal unter Anwendungsdaten erzeugt und die gesamten Daten dann dort entpackt. Funzt ganz gut.

cg

alzaimar 26. Apr 2009 09:20

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Du könntest die BLOBs auch direkt in deine EXE (oder eine separate Resource-DLL) streamen, indem Du die Daten als resource deklarierst. Dann bräuchtest Du gar keine Datenbank. Wozu auch? :gruebel:

moelski 26. Apr 2009 09:24

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Moin !

Zitat:

Du könntest die BLOBs auch direkt in deine EXE (oder eine separate Resource-DLL) streamen
:gruebel: :gruebel: Wie meinen ?

Das sind ja keine festen Daten sondern das sind die Daten die der User aufzeichnet. Und das in die EXE bzw. in eine Resourcen-DLL??

Da kann ich gerade nich folgen.

Pfoto 26. Apr 2009 09:27

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Zitat:

Zitat von moelski
Moin !
Und die kann auch Multi Thread ohne Table Lock?

Ja, das geht auf jeden Fall.
In den Beispielen gibt es extra ein Demo mit Threadbasierten Schreib- Lesezugriff.

moelski 26. Apr 2009 09:32

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Moin !

Zitat:

Ja, das geht auf jeden Fall.
In den Beispielen gibt es extra ein Demo mit Threadbasierten Schreib- Lesezugriff.
Aha, das klingt gut ...

Sorry wenn ich da nochmal extra nachhake ...
Also angenommen ich habe 4 MDI Childs. 2 sind geöffnet und beinhalten ein Bild mit jeweils 150 MB.
Die anderen beiden sind geschlossen.

Der User (angenommen er kann schnell klicken :) ) schließt nun die zwei offenen und öffnet die beiden geschlossenen.

Bedeutet:
- 2 * 150MB werden in der DB abgelegt
- 2 * 150MB werden aus der DB geladen

Und das geht ohne das der Main Thread stoppt? Wenn dem so ist, dann wäre das super.

Pfoto 26. Apr 2009 09:49

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Also soooo große Dateien habe ich nicht verwendet,
bei mir waren es ca. 1000 Bilder von je ~100kb.

Aber bei Deinen Dateigrößen könnte wohl je nach
Rechner-Power schon mal was hängen...
Hol dir doch einfach mal das Beispiel von Nexus und lade
richtig große Dateien rein.

Gruß
Jürgen

moelski 26. Apr 2009 09:56

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Moin !

Das sind natürlich nur Beispieldaten. Sozusagen der Worst Case.
Im Normalfall rechne ich eher mit 1-10MB.

Zitat:

Hol dir doch einfach mal das Beispiel von Nexus und lade
richtig große Dateien rein.
Versuche ich gerade, aber die Embedded Free Edition D2007 kann ich nicht entpacken. Sagt mir immer das Archv wäre defekt :|

Pfoto 26. Apr 2009 10:00

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Zitat:

Zitat von moelski
Moin !
Versuche ich gerade, aber die Embedded Free Edition D2007 kann ich nicht entpacken. Sagt mir immer das Archv wäre defekt :|

Das war bei mir auch so.
Es lag dann am Entpacker (ich weiß nicht mehr welcher fehlerhaft war),
auf jeden fall habe ich hier IZArc und 7-Zip
bei mir installiert und nur mit einem von beiden hatte es funktioniert.

moelski 26. Apr 2009 11:51

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Moin !

So mit was anderem als 7-zip hat es nun auch bei mir geklappt.
Ich finde da eine Demo mit Threads. Da geht es aber nur um kleine Texte die eingefügt und gelöscht werden.

@Pfoto:
Wäre es dir möglich, dass du mir ein bisserl hilfst bei einem Thread Test mit größeren Datenmengen? Ich kenne die Datenbank noch nicht wirklich.

Was mir aber schon jetzt aufgefallen ist ... die Filestruktur:
Zitat:

$SQL$FUNCTIONS.nx1
$SQL$PROCEDURES.nx1
$SQL$TRIGGERS.nx1
$SQL$VIEWS.nx1
nxTrans.cfg
table1.nx1
Alles in einzelnen Dateien. Kann man das irgendwie mergen in eine?

mkinzler 26. Apr 2009 12:02

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Wenn du eine Datei willst, solltest du dir vielleicht doch FireBird (embedded) ansehen.

moelski 26. Apr 2009 12:06

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Moin !

Naja das mit den vielen Dateien ist nicht schön, aber könnte einfach mit einer ZIP Komponente erledigt werden. Vorher entpacken, beim Schließen wieder verpacken.

alzaimar 26. Apr 2009 12:30

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Zitat:

Zitat von moelski
Zitat:

Du könntest die BLOBs auch direkt in deine EXE (oder eine separate Resource-DLL) streamen
:gruebel: :gruebel: Wie meinen?
Das sind ja keine festen Daten sondern das sind die Daten die der User aufzeichnet. Und das in die EXE bzw. in eine Resourcen-DLL??
Da kann ich gerade nich folgen.

Kukstu hier, zum Beispiel.

Alternativ baut man sich sein eigenes Datei/Streamformat, so z.B.:
Delphi-Quellcode:
unit BlobDB;
interface
uses
  Classes;

type
  TBloblDB = class
  private
    fData: TStream;
  public
// Z.B. Mit einem FileStream instantiieren, z.B:
// MyFileStream := TFileStream.Create('MyFormularData.DAT', fmOpenReadWrite);
// MyBlobDB := TBlobDB.Create (MyFileStream);
    constructor Create(aStream: TStream);
// Inhaltsverzeichnis: Name|<Blob-Größe>
    Procedure ReadContents (aDirInfo : TStrings);
// Daten unter dem Namen speichern
    procedure ReadData(aName: AnsiString; aData: TStream);
// Daten unter dem Namen überschreiben bzw. anhängen
    procedure WriteData(aName: AnsiString; aData: TStream);
// Daten unter dem Namen entfernen
    procedure DeleteData(aName: AnsiString);
// Ermitteln, ob unter dem Namen Daten vorhanden sind
    Function DataExists (aBame: AnsiString) : Boolean;
  end;

implementation
uses
  SysUtils;
type
{(*}
  TBlobHeader = record
    Name: AnsiString;
    DataSize: Integer;

    function LoadFromStream(aStream: TStream) : Boolean;
    procedure SaveToStream(aStream: TStream);
  end;
{*)}

{ TBlobHeader }
function TBlobHeader.LoadFromStream(aStream: TStream): Boolean;
var
  iLen: Integer;

begin
  if aStream.Position >= aStream.Size - 1 then
    Result := False
  else begin
    Result := True;
    aStream.ReadBuffer(iLen, SizeOf(iLen));
    setLength(Name, iLen);
    if iLen > 0 then
      aStream.Read(Name[1], iLen);
    aStream.Read(DataSize, SizeOf(DataSize));
  end;
end;


procedure TBlobHeader.SaveToStream(aStream: TStream);
var
  iLen: Integer;

begin
  iLen := Length(Name);
  aStream.WriteBuffer(iLen, SizeOf(iLen));
  aStream.WriteBuffer(Name[1], iLen);
  aStream.Write(DataSize, SizeOf(DataSize));
end;

{ TBloblDB }

constructor TBloblDB.Create(aStream: TStream);
begin
  fData := aStream;
end;

function TBloblDB.DataExists(aBame: AnsiString): Boolean;
var
  blobHeader: TBlobHeader;

begin
  fData.Position := 0;
  while blobHeader.LoadFromStream(fData) do
    if blobHeader.Name = aName then begin
      Result := True;
      Exit;
    end
    else
      fData.Position := fData.Position + blobHeader.DataSize;

  Result := False;
end;

procedure TBloblDB.DeleteData(aName: AnsiString);
var
  tmpStream: TMemoryStream;
  blobHeader: TBlobHeader;

begin
  tmpStream := TMemoryStream.Create;
  Try
  fData.Position := 0;
  while blobHeader.LoadFromStream(fData) do
    if blobHeader.Name <> aName then begin
      blobHeader.SaveToStream(tmpStream);
      tmpStream.CopyFrom(fData, blobHeader.DataSize)
    end
    else
      fData.Position := fData.Position + blobHeader.DataSize;

    fData.Position := 0;
    fData.CopyFrom(tmpStream, 0);
  finally
    tmpStream.Free;
  End;
end;

procedure TBloblDB.ReadContents(aDirInfo: TStrings);
var
  blobHeader: TBlobHeader;

begin
  fData.Position := 0;
  aDirInfo.Clear;
  while blobHeader.LoadFromStream(fData) do Begin
    aDirInfo.Add(Format('%s|%d',[blobHeader.Name, blobHeader.DataSize]));
    fData.Position := fData.Position + blobHeader.DataSize;
  End;
end;

procedure TBloblDB.ReadData(aName: AnsiString; aData: TStream);
var
  blobHeader: TBlobHeader;

begin
  fData.Position := 0;
  while blobHeader.LoadFromStream(fData) do
    if blobHeader.Name = aName then begin
      aData.CopyFrom(fData, blobHeader.DataSize);
      Exit;
    end
    else
      fData.Position := fData.Position + blobHeader.DataSize;

  raise EResNotFound.CreateFmt('Could not find: %s', [aName]);
end;

procedure TBloblDB.WriteData(aName: AnsiString; aData: TStream);
var
  blobHeader: TBlobHeader;

begin
  DeleteData(aName);
  blobHeader.Name := aName;
  blobHeader.DataSize := aData.Size;
  blobHeader.SaveToStream(fData);
  aData.Position := 0;
  fData.CopyFrom(aData, aData.Size);
end;

end.

Pfoto 26. Apr 2009 18:05

Re: Datenbank zur Ablage von (mitunter großen) Blob flieds?
 
Letztendlich bekommst du die Streams auch bei NexusDB auf
die übliche Art in die entsprechende Tabelle; entweder direkt
über TnxTable.AddFileBlob() oder über TnxQuery,
dann übergibst du vor der Ausführung den entsprechenden Stream:

DeineQuery.ParamByName('Blob').LoadFromStream(Hier DeinStream, ftBlob);

Oder auf welche Weise speichert ihr derzeit die Blobs?

Gruß
Jürgen


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:21 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz