14

テーブルと 2 つの整数で構成される主キーを持つ Sqlite3 データベースがあり、そこに大量のデータを挿入しようとしています (つまり、約 1GB 程度)。

私が抱えている問題は、主キーを作成すると暗黙的にインデックスも作成されることです。これは、私の場合、数回のコミット後にクロールへの挿入が停止することです (データベース ファイルが NFS にあるためです..ため息)。

だから、どういうわけかそのインデックスを一時的に無効にしたいと思います。これまでの私の最善の計画は、主キーの自動インデックスを削除することでしたが、SQLite はそれを好まず、そうしようとするとエラーがスローされるようです。

2 番目に良い計画は、アプリケーションがネットワーク ドライブ上にデータベースの透過的なコピーを作成し、変更を加えてからマージすることです。ほとんどの SQlite/NFS の質問とは対照的に、アクセスの同時実行は必要ないことに注意してください。

そのようなことをする正しい方法は何でしょうか?

アップデート:

既に使用しているフラグを指定するのを忘れていました:

PRAGMA synchronous = OFF
PRAGMA journal_mode = OFF
PRAGMA locking_mode = EXCLUSIVE
PRAGMA temp_store = MEMORY

更新 2: 実際にはアイテムをバッチに挿入していますが、次のバッチは前のバッチよりもコミットが遅くなります (これはインデックスのサイズに関係していると思います)。10k から 50k のタプルのバッチを試してみました。それぞれのタプルは 2 つの整数と浮動小数です。

4

3 に答える 3

11
  1. 行の唯一のアドレスであるため、埋め込みインデックスを削除することはできません。
  2. 2つの整数キーを1つの長いキーにマージ=(key1 << 32)+ key2; これをyoudスキーマのINTEGERPRIMARYKEYとして作成します(この場合、インデックスは1つだけになります)
  3. 新しいDBのページサイズを4096以上に設定します
  4. プライマリ以外の追加のインデックスを削除します
  5. 主キーが大きくなるように、SORTED順にデータを入力します。
  6. コマンドを再利用し、文字列から毎回作成しないでください
  7. ページキャッシュサイズを残りのメモリと同じ数に設定します(キャッシュサイズはページ数であり、バイト数ではないことに注意してください)
  8. 50000アイテムごとにコミットします。
  9. 追加のインデックスがある場合-すべてのデータがテーブルにある場合にのみインデックスを作成します

キーをマージして(32ビットを使用しているのに対し、sqliteは64ビットを使用しているので可能です)、ソートされた順序でデータを入力できる場合は、最初のGbを2番目と同じパフォーマンスで入力します。十分に速くなります。

于 2009-04-26T13:07:57.187 に答える
6

INSERT個々のトランザクションとして各新規を実行していますか?

BEGIN TRANSACTION行をバッチで使用する場合INSERT、インデックスは各トランザクションの最後にのみ再構築されると思います。

于 2009-04-25T10:38:14.777 に答える
3

fast-bulk-inserts-in-sqlite3 を参照してください。

于 2009-04-25T10:56:35.733 に答える