質問

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ののカスタム機能ではないことに注意してください。我々は対話型のコマンドラインインタプリタ、echosqlite3を経由して、それを渡しているので、そのようなものとして、それは奇妙な構文を持っています。

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の/

あなたは一度だけ挿入する場合は、

、私はあなたのために汚いトリックを持っていることがあります。

アイデアは、まず、バックアップ、メモリデータベースに挿入し、最終的に元のデータベースファイルに復元し、簡単です。

私は自分ので詳細な手順を書きましたブログで。 :)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top