2009-04-25 12 views
12

テーブルと2つの整数で構成されるプライマリキーを持つSqlite3データベースがあり、それに多くのデータを挿入しようとしています(つまり約1GB程度)Sqlite3:挿入中に主キーインデックスを無効にしますか?

問題はプライマリキーを作成すると暗黙的にインデックスが作成されます。私の場合は、コミット後にクロールに挿入されることがありません(データベースファイルがNFS上にあるためです)。sigh)。

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

2番目に良い計画は、ネットワークドライブ上のデータベースの透過コピーを作成し、変更してから元に戻すというアプリケーションに関係します。ほとんどのSQlite/NFSに関する質問とは対照的に、私はアクセスの同時性は必要ありません。

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

UPDATE:私はしかし、すべての次の、バッチでアイテムを挿入し、実際にいる

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

UPDATE 2:

は私がすでに使用しているフラグを指定するのを忘れバッチは以前のものよりもコミットが遅くなります(私はこれがインデックスのサイズと関係していると仮定しています)。私は10kから50kのタプルをバッチ処理しようとしました。各タプルは2つの整数と浮動小数点数です。

答えて

10
  1. 埋め込みインデックスは行の唯一のアドレスであるため、削除できません。
  2. 1つの長いキーで2つの整数キーをマージする=(key1 < < 32)+ key2;そして
  3. 主以外の任意の追加のインデックスは、データを記入取り外します(その場合、あなただけの1のインデックスを持つことになります)ヤウドスキーマでINTEGER PRIMARYキーとして少なくとも4096
  4. 新しいDB用
  5. 設定のページサイズをこれを作ります主キーが成長するように並べ替えられた順序。
  6. リユースコマンド、
  7. (キャッシュサイズは、バイト数ではないページ数であるが、ことを覚えておいてください)あなたが残っていると同じくらいのメモリに文字列
  8. 設定ページキャッシュのサイズからたびにそれらを作成していません50000アイテムごとにコミットします。
  9. あなたは追加の索引を持っている場合 - あなたは鍵をマージすることができます場合は(sqliteのは、64ビットを使用している間、私は、あなたが32ビットを使用していると思うので、それが可能だだけAFTER ALLデータがテーブルに

でそれらを作成)とソートされた順序でデータを埋める私はあなたが2番目と同じパフォーマンスで最初のGbを記入し、両方が十分に速くなるだろうと確信しています。

+0

1つのINSERT cache_sizeパラメータをチェックすると、このトリックを行うように見えます。キャッシュが明らかに多いほど、より多くのアイテムを一度に挿入できます。結局のところ、すべての終わりにコミットすることができるようにも見えます。 –

+0

さて、できます。しかし、O(1)の挿入操作の主な手口は、そのインデックスでソートされたデータを埋め込むことですが、データがメモリキャッシュに収まる場合は、すべてが本当に高速です。コミットサイズをキャッシュサイズより小さくすることは妥当です。そうしないと、sqliteは強制的にディスク上に移動します。 – Mash

6

あなたは個々の取引としてそれぞれ新しいのINSERTをやっていますか?

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

+0

です。私はあまりにもそれを提案するつもりだった:) –

+0

はい、しかし、私は1つのトランザクションにギガバイト全体を絞ることができますか?私は事故でそれをほとんど実行しましたが(コミットステートメントをどこに置いても忘れてしまった)、ディスクI/Oエラーの半分のエラーが発生しましたが、それに関連するかどうかはわかりません。 –