web-dev-qa-db-fra.com

pandas python to_sql avec sqlalchemy: comment accélérer l’exportation vers MS SQL?

J'ai une base de données avec environ 155 000 lignes et 12 colonnes . Si je l'exporte au format csv avec dataframe.to_csv, la sortie est un fichier de 11 Mo (généré instantanément).

Si, toutefois, j'exporte vers un serveur Microsoft SQL avec la méthode to_sql, cela prend entre 5 et 6 minutes! Aucune colonne n'est constituée de texte: uniquement int, float, bool et dates. J'ai vu des cas où les pilotes ODBC définissent nvarchar (max) et que cela ralentit le transfert de données, mais cela ne peut pas être le cas ici.

Des suggestions sur la manière d'accélérer le processus d'exportation? Prendre 6 minutes pour exporter 11 Mo de données rend la connexion ODBC pratiquement inutilisable.

Merci!

Mon code est:

import pandas as pd
from sqlalchemy import create_engine, MetaData, Table, select
ServerName = "myserver"
Database = "mydatabase"
TableName = "mytable"

engine = create_engine('mssql+pyodbc://' + ServerName + '/' + Database)
conn = engine.connect()

metadata = MetaData(conn)

my_data_frame.to_sql(TableName,engine)
14

La méthode DataFrame.to_sql génère des instructions d'insertion sur votre connecteur ODBC, qui sont ensuite traitées par le connecteur ODBC comme des insertions standard.

Quand c'est lent, ce n'est pas la faute des pandas.

L'enregistrement de la sortie de la méthode DataFrame.to_sql dans un fichier, puis la relecture de ce fichier sur un connecteur ODBC prendra le même temps.

Pour importer en bloc des données dans une base de données, vous devez générer un fichier csv, puis utiliser une commande de chargement, qui s'appelle dans la version MS des bases de données SQL/ BULK INSERT

Par exemple:

BULK INSERT mydatabase.myschema.mytable
FROM 'mydatadump.csv';

La syntaxe de référence est la suivante:

BULK INSERT 
   [ database_name . [ schema_name ] . | schema_name . ] [ table_name | view_name ] 
      FROM 'data_file' 
     [ WITH 
    ( 
   [ [ , ] BATCHSIZE = batch_size ] 
   [ [ , ] CHECK_CONSTRAINTS ] 
   [ [ , ] CODEPAGE = { 'ACP' | 'OEM' | 'RAW' | 'code_page' } ] 
   [ [ , ] DATAFILETYPE = 
      { 'char' | 'native'| 'widechar' | 'widenative' } ] 
   [ [ , ] FIELDTERMINATOR = 'field_terminator' ] 
   [ [ , ] FIRSTROW = first_row ] 
   [ [ , ] FIRE_TRIGGERS ] 
   [ [ , ] FORMATFILE = 'format_file_path' ] 
   [ [ , ] KEEPIDENTITY ] 
   [ [ , ] KEEPNULLS ] 
   [ [ , ] KILOBYTES_PER_BATCH = kilobytes_per_batch ] 
   [ [ , ] LASTROW = last_row ] 
   [ [ , ] MAXERRORS = max_errors ] 
   [ [ , ] ORDER ( { column [ ASC | DESC ] } [ ,...n ] ) ] 
   [ [ , ] ROWS_PER_BATCH = rows_per_batch ] 
   [ [ , ] ROWTERMINATOR = 'row_terminator' ] 
   [ [ , ] TABLOCK ] 
   [ [ , ] ERRORFILE = 'file_name' ] 
    )] 
11
firelynx

Vous pouvez utiliser d6tstack qui dispose de fast pandas en fonctionnalité SQL car il utilise des commandes d’importation de base de données natives. Il supporte MS SQL, Postgres et MYSQL

uri_psql = 'postgresql+psycopg2://usr:pwd@localhost/db'
d6tstack.utils.pd_to_psql(df, uri_psql, 'table')
uri_mssql = 'mssql+pymssql://usr:pwd@localhost/db'
d6tstack.utils.pd_to_mssql(df, uri_mssql, 'table', 'schema') # experimental

Également utile pour importer plusieurs fichiers CSV avec des modifications de schéma de données et/ou un prétraitement avec des pandas avant d’écrire dans db, voir plus bas dans cahier d’exemples

d6tstack.combine_csv.CombinerCSV(glob.glob('*.csv'), 
    apply_after_read=apply_fun).to_psql_combine(uri_psql, 'table')
0
citynorman