STDINバイナリからのコピーを使用してPostgreSQLに大量のデータをロードする速度を上げる

序文





私は自宅でPostgreSQLを学んでおり、大量のデータの処理を本当に楽しんでいます。QtフレームワークでC / C ++で書いています。残念ながら、Qtポストドライバーは高速読み込みに必要な機能をサポートしていません。したがって、私はこのためにC ++でライブラリを作成しました。次に、このすばらしい追加方法とライブラリ自体を共有したいと思います。









こんにちは$ユーザー名!





今日は、PostgreSQL DBMS(以下「postik」と呼びます)への高速データロードについて説明します。これは、ネットワークを介してバイナリ形式でデータを転送するCOPYメカニズムを介して行います。









まず、次を追加するこの方法の利点を検討してください。





  • 非常に速い追加速度





    すべては、データ処理(さまざまな変換)の必要性を最小限に抑えるという事実によるものです。投稿は、正しい形式を使用しているかどうかを確認するだけで済みます。





  • テキスト形式とは対照的に、データが失われることはありません。





    たとえば、これが2つの数値でどのように発生する可能性がありますか。この方法では、小数点の前後の桁数を把握する必要はありません。データは「そのまま」送信されます。









この投稿では、ドキュメントに記載されているすべての詳細を開示するわけではありません。簡単なaddメソッドを作成します。詳細やその他のものなしで。コードで呼び出されるすべての関数は、「libpq-fe.h」ライブラリの関数です。また、すべてのコードはC / C ++で記述されます。





バイナリバッファを作成するためのアルゴリズム

バッファ構造:





[バッファ開始ヘッダー]





{データ文字列}





{データ文字列}





{データ文字列}





..。..。..。





{データ文字列}





[ ]













:





  • COPY-





'P','G','C','O','P','Y','\n','\377','\r','\n','\0'
      
      







'\0','\0','\0','\0'
      
      



, OID – 16- 1









'\0','\0','\0','\0'
      
      



, . , .









  • ( 13.1 ), .













:









int16_t , , . , , , .





  • :





    1)





    , ,





    2)









, :





.





int64_t , . ( ). , - . , COPY TO



, .













0xff, 0xff
      
      



. , — , ( -1).





  • , —





string conninfo = 
  "host=127.0.0.1 port=5432 dbname=postgres user=postgres password=postgres connect_timeout=10";
PGconn *conn = PQconnectdb(conninfo.c_str());
// conninfo -     ( connect_timeout    )

      
      



  • COPY-





pg_result *res = PQexec(conn, cquery);
      
      



cquery COPY . COPY testtable5 ( col1, col2, col3, col4 ) FROM STDIN (format binary);















PQputCopyData(conn, buf, currentSize);
      
      



, buf – , currentSize — .









, . . 2-128 .





  • ,





PQputCopyEnd(conn, NULL);
      
      







!





.





? , int16_t tmp = 2;



: 0x02, 0x00



0x00, 0x02



. . SPARC . , SPARC-, ( )





.

Qt:





db.open();
QSqlQuery query(db);
query.prepare("insert into testtable5 ( col1, col2, col3, col4 ) values (?,?,?,?);");
for(int i=0; i<20000000; i++)
{
    query.addBindValue("column1");
    query.addBindValue(double(12983712987.4383453947384734853872837));
    query.addBindValue(int(12345678));
    query.addBindValue(float(123.4567));
    query.exec();
}
      
      







( ) 10.000 - Y, - - X.









COPY INSERT .





- INSERT- .





- INSERT- .





- COPY- .





- COPY- .





INSERT .





- INSERT- .





- INSERT- .





COPY .





- COPY- .





- COPY- .





.





:





10.000 ( ), :





12.620 INSERT





12.050 INSERT





150 COPY





120 COPY





... COPY. , .





— . , , , .





GitHub





COPY









P.S.: , .





.








All Articles