質問
sqlite3 データベースにロードしたい、約 30000 行のデータのファイルがあります。データの各行に対して挿入ステートメントを生成するよりも速い方法はありますか?
データはスペースで区切られており、sqlite3 テーブルに直接マップされます。データベースにボリューム データを追加するための一括挿入方法はありますか?
組み込まれていない場合、これを行うための非常に素晴らしい方法を誰かが考案したことがありますか?
前置きとして、API から C++ でそれを行う方法はありますか?
解決
また、それの外に余分な速度を得るためにのいくつかのパラメータを微調整を試すことができます。具体的には、おそらくPRAGMA synchronous = OFF;
を望んでます。
他のヒント
- すべての INSERT をトランザクション内でラップすると、たとえユーザーが 1 人であっても、はるかに高速になります。
- 準備されたステートメントを使用します。
あなたは.import
コマンドを使用します。たとえばます:
$ cat demotab.txt
44 92
35 94
43 94
195 49
66 28
135 93
135 91
67 84
135 94
$ echo "create table mytable (col1 int, col2 int);" | sqlite3 foo.sqlite
$ echo ".import demotab.txt mytable" | sqlite3 foo.sqlite
$ sqlite3 foo.sqlite
-- Loading resources from /Users/ramanujan/.sqliterc
SQLite version 3.6.6.2
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select * from mytable;
col1 col2
44 92
35 94
43 94
195 49
66 28
135 93
135 91
67 84
135 94
このバルクロードコマンドはSQLではなく、SQLiteののカスタム機能ではないことに注意してください。我々は対話型のコマンドラインインタプリタ、echo
にsqlite3
を経由して、それを渡しているので、そのようなものとして、それは奇妙な構文を持っています。
PostgreSQLでは同等のCOPY FROM
です。
http://www.postgresql.org/docs/8.1/static/sql -copy.htmlする
MySQLでは、それはLOAD DATA LOCAL INFILE
です。
http://dev.mysql.com/doc/refman/5.1 /en/load-data.htmlする
最後の一つです:.separator
の値に注意してくださいすることを忘れないでください。一括挿入を行う場合には非常に一般的な落とし穴です。
sqlite> .show .separator
echo: off
explain: off
headers: on
mode: list
nullvalue: ""
output: stdout
separator: "\t"
width:
は、明示的.import
を行う前にスペース、タブ、またはカンマする区切り文字を設定する必要があります。
増加
PRAGMA default_cache_size
はるかに大きな数に。これにより、メモリにキャッシュされたページ数が増加します。すべての挿入を行ごとに 1 つのトランザクションではなく、単一のトランザクションにラップします。
- コンパイルされた SQL ステートメントを使用して挿入を実行します。
- 最後に、すでに述べたように、完全な ACID 準拠を放棄する場合は、次のように設定します。
PRAGMA synchronous = OFF;
.
RE:「?データの行ごとにINSERT文を生成することをより高速な方法はあります」
まず:仮想テーブルAPIを利用して2つのSQL文にそれをダウンカット>例えば
create virtual table vtYourDataset using yourModule;
-- Bulk insert
insert into yourTargetTable (x, y, z)
select x, y, z from vtYourDataset;
ここでの考え方は、あなたがあなたの元データが設定読み込みCインタフェースを実装し、それを仮想表としてSQLiteのために、次にあなたが一度にターゲット表にソースからSQLコピーを行う提示していることです。それは実際にあると私は巨大な速度の向上をこのように測定してきたよりも硬い鳴ります。
第二:ここで提供される他のアドバイスをご利用くださいすなわち、プラグマの設定と取引を利用して、
。第三:あなたは離れて、ターゲット表上の索引の一部で行うことができるかどうか、おそらく参照してください。その方法のSQLiteは挿入された行ごとに更新するより少ないインデックスを有するであろう
は、一括挿入する方法はありませんが、 大きなチャンクを書き込むための方法があります メモリに、そしてそれらをコミットします データベース。 C / C ++ APIの場合は、ちょうど行います:
sqlite3_exec(デシベル、 "BEGIN TRANSACTIONを"、 NULL、NULL、NULL);
...(INSERT文)
sqlite3_exec(DB、 "トランザクションをコミット"、NULL、NULL、NULL);
DBは、データベースのポインタであると仮定します。
良好な妥協はBEGINの間にあなたの挿入をラップすることです。そして終わり;キーワードすなわちます:
BEGIN;
INSERT INTO table VALUES ();
INSERT INTO table VALUES ();
...
END;
データのサイズと使用可能なRAMの量に応じて、最高のパフォーマンス向上の一つではなく、ディスクへの書き込みよりも、オール・イン・メモリデータベースを使用するようにsqliteのを設定することによって発生します。
のインメモリ・データベースの場合、ファイル名の引数はsqlite3_open
するとしてNULLを渡すと確認TEMP_STOREことを確認適切に定義されているを
(上記のテキストはすべて、別のsqlite-に私自身の答えから抜粋されます関連する質問する)
私は、これはワンショットの長いインポートの良いミックスであることが判明します。
.echo ON
.read create_table_without_pk.sql
PRAGMA cache_size = 400000; PRAGMA synchronous = OFF; PRAGMA journal_mode = OFF; PRAGMA locking_mode = EXCLUSIVE; PRAGMA count_changes = OFF; PRAGMA temp_store = MEMORY; PRAGMA auto_vacuum = NONE;
.separator "\t" .import a_tab_seprated_table.txt mytable
BEGIN; .read add_indexes.sql COMMIT;
.exit
ソース:ます。http://erictheturtle.blogspot。 2009/05 /こと/最速一括インポート-に-sqlite.htmlする
いくつかの追加情報:のhttp://blog.quibb .ORG / 2010/08 /高速バルク挿入-に、SQLiteの/ の
、私はあなたのために汚いトリックを持っていることがあります。
アイデアは、まず、バックアップ、メモリデータベースに挿入し、最終的に元のデータベースファイルに復元し、簡単です。
私は自分ので詳細な手順を書きましたブログで。 :)