Beschleunigen Sie das Laden großer Volumes in PostgreSQL mit COPY aus der STDIN-Binärdatei

Vorwort





Ich lerne PostgreSQL zu Hause und genieße es wirklich, große Datenmengen zu verarbeiten. Ich schreibe in C / C ++ auf dem Qt-Framework. Leider unterstützt der Qt-Post-Treiber nicht die für das schnelle Laden erforderlichen Funktionen. Deshalb habe ich meine Bibliothek in C ++ dafür geschrieben, und jetzt möchte ich diese wunderbare Methode des Hinzufügens und die Bibliothek selbst mit Ihnen teilen.









Hallo $ Benutzername!





Heute werden wir über das schnelle Laden von Daten in PostgreSQL DBMS (im Folgenden als "postik" bezeichnet) sprechen. Wir werden dies durch den COPY-Mechanismus mit der Übertragung von Daten über das Netzwerk in einem Binärformat tun.









Betrachten Sie zunächst die Vorteile dieser Methode des Hinzufügens:





  • Sehr schnelle Addiergeschwindigkeit





    Alles ist darauf zurückzuführen, dass wir die Notwendigkeit der Datenverarbeitung (verschiedene Transformationen) auf ein Minimum reduzieren. Der Beitrag muss nur prüfen, ob wir das richtige Format verwenden.





  • Im Gegensatz zum Textformat verlieren wir keine Daten.





    Wie kann dies beispielsweise mit einer doppelten Zahl geschehen? Wir müssen bei dieser Methode nicht herausfinden, wie viele Stellen vor und nach dem Dezimalpunkt stehen. Die Daten werden "wie sie sind" übertragen.









In diesem Beitrag werde ich nicht alle Details offenlegen, die in der Dokumentation beschrieben sind. Wir werden nur eine einfache Additionsmethode schreiben, d. H. ohne Einzelheiten und andere Dinge. Alle Funktionen, die im Code aufgerufen werden, sind Funktionen aus der Bibliothek „libpq-fe.h“. Außerdem wird der gesamte Code in C / C ++ geschrieben.





Algorithmus zum Erstellen eines Binärpuffers

Pufferstruktur:





[Pufferstart-Header]





{Datenzeichenfolge}





{Datenzeichenfolge}





{Datenzeichenfolge}





... ... ...





{Datenzeichenfolge}





[ ]













:





  • 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