SQLiteデータベースをマージすると、私は気が狂ってしまいます。助けて?

私は32個のSQLite(3.7.9)データベースを持っています。それぞれ3つのテーブルを持っています。別のところで見つけたイディオムを使用して結合しようとしています(各データベースに同じスキーマがあります)。

attach db1.sqlite3 as toMerge;
insert into tbl1 select * from toMerge.tbl1;
insert into tbl2 select * from toMerge.tbl2;
insert into tbl3 select * from toMerge.tbl3;
detach toMerge;

およびデータベース全体のリンスを繰り返します。私はこれをpythonとsqlite3モジュールを使って行います:

  for fn in filelist:

    completedb = sqlite3.connect("complete.sqlite3")
    c = completedb.cursor()

    c.execute("pragma synchronous = off;")
    c.execute("pragma journal_mode=off;")

    print("Attempting to merge " + fn + ".")
    query = "attach '" + fn + "' as toMerge;"
    c.execute(query)

    try:
        c.execute("insert into tbl1 select * from toMerge.tbl1;")
        c.execute("insert into tbl2 select * from toMerge.tbl2;")
        c.execute("insert into tbl3 select * from toMerge.tbl3;")
        c.execute("detach toMerge;")
        completedb.commit()
    except sqlite3.Error as err:
        print "Error! ", type(err), " Error msg: ", err
        raise

2 of the tables are fairly small, only 50K rows per db, while the third (tbl3) is larger, about 850 - 900K rows. Now, what happens is that the inserts progressively slow down until I get to about the fourth database when they grind to a near halt (on the order of a a megabyte or two in file size added every 1-3 minutes to the combined database). In case it was python, I've even tried dumping out the tables as INSERTs (.insert; .out foo; sqlite3 complete.db < foo is the skeleton, found here) and combining them in a bash script using the sqlite3 CLI to do the work directly, but I get exactly the same problem.

tbl3のテーブル設定はそれほど厳しいものではなく、UUID、2つの整数、4つの実数値を含むテキストフィールドです。私が心配しているのは、行数です。なぜなら、個々のデータベースが同じ数の行でファイルサイズの点で大きかった場合、まったく同じ問題(正確には同じ4つのデータベース)で同じ問題が発生したからです(私は生データの代わりに要約統計量を保存することによってtbl3の内容を大幅にトリミングしました)。それとも、それは私が操作を実行している方法ですか?窓から何かを投げる前に、誰かがこの問題について何か光を当てることができますか?

1

2 答え

大きな表の索引/主キーを追加または削除してみてください。

1
追加された

使用していたOSやdbファイルのサイズについては言及していませんでした。 Windowsは、どのバージョンに応じて2Gbを超えるファイルに関する問題が発生する可能性があります。

いずれにせよ、これは栄光のバッチスクリプトなので、 for ループを取り除かないと、 sys.argv からファイル名を取得し、 merge db。そうすれば、メモリの問題を1つのプロセスで多すぎることから決して処理する必要はありません。

ループを終了させて​​次のようなことをしても、状況を修正する可能性が高いことに気をつけてください。

c.close()
completedb.close()

CLIを使用してこのプロセスを実行し、すべてのdbの後に終了するときにも同じことが起こると言います。私はあなたがPython CLIを意味していると仮定し、終了するとPythonを終了して再起動することを意味します。それが本当であり、それでも4番目のデータベースごとに問題が発生する場合は、SQLITE共有ライブラリに問題があります。そのような状態を保つべきではありません。

私があなたの靴を履いていたら、 attach の使用をやめ、Pythonで複数の接続を開き、コミットあたり約1000レコードのバッチでデータを移動します。すべてのデータがPythonオブジェクトの内外に移動するため、これはあなたの手法よりも遅くなりますが、信頼性も高くなると思います。完全なdbを開き、2番目のdbを開いてコピーしてから、2番目のdbを閉じます。コピーするには、SELECT文でOFFSETとLIMITを使用して、100レコードのバッチを処理し、コミットしてから、繰り返します。 実際には、完成したbレコードと、コピーする前の2番目のdbレコードもカウントして、コピーした後、完成したbレコードをカウントして、予想される量をコピーしたことを確認します。また、次のOFFSETの値を記録しておき、コミット直後にテキストファイルに書き込むので、いつでもプロセスを中断して再開でき、途中で中断してしまうことがあります。

1
追加された
マイケル、答えに感謝します。 Re:あなたの質問、OS X LionとRocksクラスタのヘッドノードで試しました(5.3)。私が言及したように、問題はデータベースのファイルサイズに依存しません。現在のインカネーションではそれぞれ160 Mbですが、1.6 Gbの場合とまったく同じように問題が発生しました。あなたの提案:私は前にc.close()とcompletedb.close()を使ってみましたが、このコードから除外しました。問題は修正されませんでした。私はCLIを使って手動でこれをやってみました - それを開始し、アタッチし、マージし、終了し、各ファイルについて繰り返します。運がない。
追加された 著者 Winawer,