7

編集:すべての回答に感謝します。これまでの最適化を適用した後の結果は次のとおりです。

  • 文字のソートとランレングス エンコーディングへの切り替え - 新しい DB サイズ 42M
  • ブール値のインデックスを削除 - 新しい DB サイズ 33M

本当に素晴らしいのは、iPhone のコードを変更する必要がないことです。

sqlite 形式 (読み取り専用) で保持されている大きな辞書を持つ iPhone アプリケーションがあります。現在非常に大きい DB ファイルのサイズを小さくするためのアイデアを探しています。

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

...エントリあたり平均約 135 バイト。

ここに私のDBスキーマがあります:

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)

サンプルデータは次のとおりです。

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

最後のフィールドは、アナグラム検索の文字頻度を表します (各位置は 0..9 の範囲にあります)。2 つのブール値はサブディクショナリを表します。

次のようなクエリを実行する必要があります。

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')

私が持っている 1 つのアイデアは、文字の頻度をより効率的にエンコードすることです。たとえば、それらを blob としてバイナリ エンコードします (多くのゼロがあるため、おそらく RLE を使用しますか?)。これを達成するための最善の方法、またはサイズを縮小するための他のアイデアはありますか? 私はルビーでDBを構築し、目的のCで電話でそれを読んでいます.

また、DB の統計を取得して、最も多くのスペースを使用しているものを確認する方法はありますか?

4

11 に答える 11

5

「vacuum」コマンドを入力して、再利用するのを忘れたデータベースに余分なスペースがないことを確認しましたか?

于 2008-12-30T21:10:29.500 に答える
4

sowpods と twl のインデックスを削除します。これらはおそらくクエリ時間には役立たず、間違いなく多くのスペースを占有しています。

SQLite ダウンロード ページからsqlite3_analyzerを使用してデータベースの統計を取得できます。

于 2008-12-30T23:33:30.303 に答える
3

まったく異なるアプローチとして、包括的なデータベースの代わりにブルームフィルターを使用してみることができます。基本的に、ブルームフィルターは一連のハッシュ関数で構成され、各関数はビットフィールドに関連付けられています。有効な単語ごとに、各ハッシュ関数が評価され、対応するビットフィールドの対応するビットが設定されます。欠点は、理論的には誤検知が発生する可能性があることですが、十分なハッシュを使用することで、これらを最小限に抑えることができます。プラス面は、大幅なスペース節約です。

于 2008-12-30T21:57:06.020 に答える
2

署名フィールドのすべての使用例については明確ではありませんが、代わりに単語のアルファベット順バージョンを保存すると有益なようです。

于 2008-12-30T21:08:56.710 に答える
1

最善の策は圧縮を使用することですが、残念ながら現時点では SQLite がネイティブにサポートしていません。幸いなことに、誰かが時間をかけて圧縮拡張機能を開発してくれました。

それ以外の場合は、データをほとんど圧縮形式で保存し、その場で解凍することをお勧めします。

于 2008-12-30T20:59:13.923 に答える
1

SQLite の作成者は、データベース圧縮 (および暗号化) を含むバージョンの SQLite を販売しています。これは完璧でしょう。

于 2008-12-30T21:01:53.200 に答える
1

テキスト フィールドとして、signature現在、エントリごとに少なくとも 26 * 8 バイト (208 バイト) を使用していますが、データをビットフィールドにパックする場合、文字ごとに 3 ビットしか使用できない可能性があります (文字ごとの最大頻度を減らします)。 7)に。これは、署名全体を 26 * 3 ビット = 78 ビット = 10 バイトでパックできることを意味します。文字あたり 4 ビットを使用したとしても (文字あたり最大頻度 15)、104 ビット (13 バイト) しか使用しません。

編集: もう少し考えた後、1 文字あたり 4 ビット (3 ではなく) の方が良いと思います。2 進数の計算が簡単になるからです。

EDIT2: SQLiteデータ型に関するドキュメントを読むと、「署名」フィールドをINTEGER型の26列にまたがらせることができるようで、SQLiteは正しいことを行い、保存するために必要な数のビットのみを使用します価値。

于 2008-12-30T21:13:31.897 に答える
0

うーん...iPhone...永続的なデータ接続がありませんか?これは、webapplication/webserviceがぴったりとジャンプできる場所だと思います。ほとんどのビジネスロジックをWebサーバーに移動し(彼はFTSと大量のメモリを備えた実際のSQLを使用する予定です)、その情報をデバイス上のクライアントにオンラインでフェッチします。

于 2008-12-30T21:53:42.690 に答える
0

他の場所で述べたように、ブール列のインデックスを失うと、テーブル スキャンよりも (使用されたとしても) ほぼ確実に遅くなり、スペースを不必要に使用することになります。

単語に単純な圧縮を適用することを検討したいと思います。ハフマン コーディングは、この種の処理にはかなり適しています。また、署名を調べます。列を文字の頻度順に並べ替えます。暗示される可能性のある末尾のゼロをわざわざ保存しないでください。それらもハフマンエンコードできると思います。

もちろん、エンコードされた文字列が SQLite を混乱させないことを常に前提としています。

于 2008-12-31T14:07:47.980 に答える
0

あなたのデータベースには、そのような単語が約 450K あると思いますか?

私はiPhoneについての手がかりがなく、sqlitemについても真剣ではありませんが... sqliteがファイルをgzとしてすぐに保存する方法を許可しない限り(おそらくすでに内部的に行われていますか?いいえ、そのようには見えませんエントリごとに約 135 b だとおっしゃいましたが、両方のインデックスを使用しても、テーブル アプローチから離れて、辞書アプローチ圧縮で「手動で」保存し、残りをその場でメモリ内に構築します。それはあなたのタイプのデータで非常にうまく機能するはずです。

待って...その署名を使用して、全文検索や誤入力認識を可能にしていますか? sqlite での全文検索はそのフィールドを廃止しませんか?

于 2008-12-30T21:06:21.460 に答える
0

前述のように、「署名」をより効率的に保存することは良い考えのようです。

ただし、単語のルックアップテーブルを使用することで、大量のスペースを節約できるようにも見えます-ルート単語を取得してから「er」、「ed」、「es」などを追加しているように見えるためです。別のルックアップ テーブルからルート ワードを参照する数値 ID を持つ列と、ベース ワードに追加される一般的な単語の接尾辞のテーブルを参照する数値 ID を持つ別の列はありません。

単一の語根を持つ複数のエントリの署名の省略形を保存する際にトリックがあった場合は、それらを使用して、保存された署名のサイズを縮小することもできます (どのアルゴリズムがそれらの値を生成しているかはわかりません)。

「単語」列を主キーとして持っているので、これは私にも非常に理にかなっているようですが、インデックスを付けることさえしません。テーブルの主IDである別の数値列を作成するだけです。

于 2008-12-30T21:47:45.977 に答える