Frage

Bearbeiten: Vielen Dank für alle Antworten. Hier sind die Ergebnisse nach den Optimierungen der Anwendung so weit:

  • Die Umstellung auf die Zeichen und Lauflängencodierung Sortierung - neue DB Größe 42M
  • Dropping die Indizes für die Boolesche Werte - neue DB Größe 33M

Der wirklich schöne Teil wird diese Änderungen in dem iphone-Code nicht erforderlich ist

Ich habe eine iPhone-Anwendung mit einem großen Wörterbuch in SQLite-Format gehalten (nur lesen). Ich bin die Suche nach Ideen, die Größe der DB-Datei zu reduzieren, die zur Zeit sehr groß ist.

Hier ist die Anzahl der Einträge und die daraus resultierende Größe der SQLite-DB:

franks-macbook:DictionaryMaker frank$ ls -lh dictionary.db
-rw-r--r--  1 frank  staff    59M  8 Oct 23:08 dictionary.db
franks-macbook:DictionaryMaker frank$ wc -l dictionary.txt
  453154 dictionary.txt

... ein Durchschnitt von etwa 135 Bytes pro Eintrag.

Hier ist mein DB-Schema:

create table words (word text primary key, sowpods boolean, twl boolean, signature text)
create index sowpods_idx on words(sowpods)
create index twl_idx on words(twl)
create index signature_idx on words(signature)

Hier finden Sie einige Beispieldaten:

photoengrave|1|1|10002011000001210101010000
photoengraved|1|1|10012011000001210101010000
photoengraver|1|1|10002011000001210201010000
photoengravers|1|1|10002011000001210211010000
photoengraves|1|1|10002011000001210111010000
photoengraving|1|1|10001021100002210101010000

Das letzte Feld stellt die Buchstaben Frequenzen für Anagramm Retrieval (jede Position im Bereich 0..9). Die beiden booleans repräsentieren Unter Wörterbücher.

Ich brauche, um Abfragen zu tun wie:

select signature from words where word = 'foo'
select word from words where signature = '10001021100002210101010000' order by word asc
select word from words where word like 'foo' order by word asc
select word from words where word = 'foo' and (sowpods='1' or twl='1')

Eine Idee, die ich habe, ist die Buchstabenfrequenzen effizienter zu kodieren, z.B. binär kodieren sie als Blob (vielleicht mit RLE, da es viele Nullen sind?). Irgendwelche Ideen, wie dies am besten zu erreichen, oder andere Ideen, um die Größe zu reduzieren? Ich baue die DB in Rubin, und es am Telefon in Objective C. Lesen

Auch ist es eine Möglichkeit, Statistiken über die DB zu bekommen, so kann ich sehen, was den meisten Platz verwendet?

War es hilfreich?

Lösung

Ich bin auf alle Anwendungsfälle für das Signaturfeld nicht klar, aber es scheint, als ob stattdessen eine alphabetisch sortierte Version des Wortes Speicherung von Vorteil wäre.

Andere Tipps

Haben Sie versucht, das „Vakuum“ Befehl eingeben, um sicherzustellen, Sie haben nicht mehr Platz in der db Sie reclame vergessen?

Entfernen Sie die Indizes für SOWPODS und twl -. Sie sind wahrscheinlich die Abfragezeiten nicht zu helfen und werden auf jeden Fall viel Platz nehmen

Sie können Statistiken über die Datenbank erhalten mit sqlite3_analyzer aus der SQLite-Download-Seite .

Als völlig anderen Ansatz, könnten Sie versuchen, eine Bloom-Filter anstelle eines umfassenden Datenbank. Grundsätzlich ist ein Bloom-Filter besteht aus einem Bündel von Hash-Funktionen, von denen jede mit einem Bitfeld zugeordnet ist. Für jedes Wort Recht wird jede Hash-Funktion ausgewertet werden, und das entsprechende Bit in dem entsprechenden Bit-Feld wird gesetzt. Nachteil ist es theoretisch möglich ist falsch positive Ergebnisse zu bekommen, aber diejenigen, minimiert werden kann / praktisch mit genug Hashes eliminiert. Plus-Seite ist ein großes Platzersparnis.

Der Schöpfer von SQLite verkauft eine Version von SQLite, die Datenbank-Komprimierung (und Verschlüsselung) enthält. Dies wäre perfekt.

Ihre beste Wette ist Komprimierung zu verwenden, die leider SQLite nicht nativ an dieser Stelle nicht unterstützt. Glücklicherweise nahm jemand die Zeit, ein Kompression Erweiterung für sie zu entwickeln, das sein könnte, was Sie brauchen.

Ansonsten würde ich empfehlen, die Daten meist in komprimiertem Format zu speichern und Dekomprimieren on the fly.

Als Textfeld signature derzeit mit mindestens 26 * 8 Bytes pro Eintrag (208 Bytes), aber wenn Sie die Daten in ein Bitfeld packen, könnte man wahrscheinlich mit nur 3 Bits pro Brief weg (Reduzierung Ihres Höchstfrequenz pro Buchstaben bis 7). Das würde bedeuten, Sie die gesamte Signatur in 26 * 3 Bit packen konnten = 78 Bit = 10 Byte. Selbst wenn Sie 4 Bits pro Buchstaben verwendet (für eine maximale Frequenz von 15 pro Brief) nur 104 Bit (13 Byte) verwenden würde.

EDIT:. Nach ein bisschen mehr Gedanken, ich denke, 4 Bits pro Brief (statt 3) eine bessere Idee wäre, weil es die binäre Mathematik leichter machen würde

EDIT2: die Dokumentation Beim Lesen auf SQLite-Datentypen , scheint es, dass Sie vielleicht können nur die „Signatur“ Feld Spannweite 26 Spalten des Typs INTEGER und SQLite, das richtige und nur so viele Bits wie erforderlich speichern den Wert verwenden, tun machen.

Habe ich richtig rechne, dass Sie über 450K Wörter wie, dass in Ihrer Datenbank?

Ich habe keine Ahnung von iPhone bekam, weder ernsthaft über sqlitem aber ... solange SQLite nicht zulässt eine Möglichkeit, die Datei als gz sofort zu speichern (es vielleicht schon intern nicht? Nein, sieht nicht so aus so, wenn Sie sagen es etwa 135 b pro Eintrag ist. nicht einmal beiden Indizes mit), würde ich vom Tisch Ansatz abrücken, sie „von Hand“ in einem Wörterbuch Ansatz Kompression und den Rest im Fluge bauen und im Speicher. Das sollte sehr gut auf Ihre Art von Daten durchführen.

Warten Sie

... Verwenden Sie diese Signatur für fulltextsearching zu ermöglichen oder recogition Vertippen? Würde Volltextsuche auf SQLite nicht veraltet, dass Feld?

Wie bereits erwähnt Speicher „Signature“ effiziente wie eine gute Idee zu sein scheinen.

Allerdings scheint es auch, wie Sie durch den Einsatz eine Art Lookup-Tabelle für Wörter eine Tonne Platzersparnis gewinnen konnte - da Sie scheinen ein Stammwort zu nehmen und dann „er“, „ed“, „es“ anhängt etc, warum nicht eine Spalte mit einer numerischen ID hat, die ein Stammwort von einer separaten Lookup-Tabelle verweist, und dann eine eigene Spalte mit einer numerischen ID, die eine Tabelle von gemeinsamem Wort Suffixe verweist, die auf das Grundwort angehängt werden würden.

Wenn es um irgendwelche Tricks Stenografie Versionen von Signaturen für mehrere Einträge mit einem einzigen Stammwort zu speichern, könnten Sie auch diejenigen einsetzen, um die Größe der gespeicherten Signaturen zu reduzieren (nicht sicher, welcher Algorithmus die Werte produzierend)

Dies scheint auch viel Sinn für mich zu machen, wie Sie das „Wort“ Spalte als Primärschlüssel haben, aber nicht einmal indizieren -. Nur eine separate numerische Spalte erstellen, die die primäre ID für die Tabelle ist

mhmm ... ein iPhone ... ist es nicht eine permanente Datenverbindung hat? Ich denke, das ist, wo eine Webapplikation / webservice in eng springen kann. Bewegen Sie die meisten Ihrer Geschäftslogik auf den Webserver (er wird haben echte SQL mit FTS und looooots Speicher) und holen diese Informationen online an den Client auf dem Gerät.

Wie an anderer Stelle erwähnt, verliert die Indizes für die boolean Spalten, werden sie mit ziemlicher Sicherheit langsamer sein (wenn überhaupt) als eine Tabellensuche und geht Raum nutzen unnötig.

Ich halte würde eine einfache Kompression auf die Worte der Anwendung Huffman-Kodierung ist ziemlich gut für diese Art der Sache. Außerdem würde ich die Unterschriften aussehen: die Spalten in Häufigkeit von Buchstaben Reihenfolge sortieren und nicht die Mühe machen nachfolgende Nullen zu speichern, die impliziert werden kann. Ich denke, man könnte Huffman-Codierung diejenigen, auch.

Immer vorausgesetzt, Ihre codierten Zeichenkette nicht aufregen SQLite, natürlich.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top