2015-04-17 6 views
13

Mam ramkę danych z około 155 000 wierszy i 12 kolumnami. Jeśli wyeksportuję go do pliku csv za pomocą metody dataframe.to_csv, wynikiem jest plik o wielkości 11 MB (który jest natychmiast tworzony).python pandas to_sql z sqlalchemy: jak przyspieszyć eksport do MS SQL?

Jeśli jednak eksportuję do serwera Microsoft SQL Server za pomocą metody to_sql, zajmuje to od 5 do 6 minut! Brak kolumn to tekst: tylko int, float, bool i date. Widziałem przypadki, w których sterowniki ODBC ustawiały nvarchar (max), co spowalnia transmisję danych, ale nie może tak być w tym przypadku.

Jakieś sugestie, jak przyspieszyć proces eksportu? Zajęcie 6 minut na eksport 11 MB danych sprawia, że ​​połączenie ODBC praktycznie nie nadaje się do użytku.

Dzięki!

Mój kod to:

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) 
+0

Jedyne co mogę myśleć jest eksport tylko strukturę, czyli nazwy kolumn i typów danych, ale nie wierszy, S QL, a następnie wyeksportuj plik do pliku CSV i użyj czegoś takiego jak kreator importu/eksportu, aby dołączyć plik CSV do tabeli SQL. W ten sposób nie muszę ponownie definiować wszystkich typów kolumn; jest to ważne, ponieważ narzędzia do importowania mają tendencję do czytania pierwszych x wierszy do odgadywania typów danych, a jeśli pierwsze wiersze są wszystkie NULL, to domysły będą błędne. Jednak faktem jest, że metoda to_sql jest praktycznie bezużyteczna, z wyjątkiem małych tabel. Czy doświadczyłeś tego również w innych bazach danych? –

+1

Próbowałem tego samego w domu, z SQL Server Express działa na moim komputerze, a python trwało 2 minuty, aby przenieść ramkę danych z 1 milionem wierszy x 12 kolumnami liczby losowej do SQL (rozmiar w CSV = 228 MB). Nie super szybki, ale do zaakceptowania. Zajęło to 6 minut (w przypadku znacznie mniejszego pliku) na komputerze roboczym łączącym się z serwerem SQL w odległości zaledwie kilku mil. Czy wiesz, czy istnieje jakiś parametr w pandach, sqlalchemy lub pyodbc, aby przyspieszyć transfer? Łączę się z tym samym serwerem SQL z wieloma innymi narzędziami i nigdy nie jest tak powolny. Dzięki! –

+1

Ktoś? Sprawdziłem również, że metoda pandas.read_sql_table jest dość szybka. Pisanie odbywa się powoli, nawet przy pisaniu tabeli bez ograniczeń. Jakieś pomysły? Nie mogę być jedyną osobą, która kiedykolwiek doświadczyła tego, ale wydaje mi się, że cnanot znajduje jakąkolwiek dokumentację na ten temat w Internecie ... :( –

Odpowiedz

6

Sposób DataFrame.to_sql generuje INSERT do swojego łącznika ODBC, który następnie poddaje się obróbce przez złącze ODBC jako zwykłych wkładek.

Gdy jest to powolne, nie jest to wina pand.

Zapisywanie danych wyjściowych metody DataFrame.to_sql do pliku, a ponowne odtwarzanie tego pliku przez złącze ODBC zajmuje tyle samo czasu.

Właściwym sposobem luzem importowanie danych do bazy danych jest generowanie pliku csv, a następnie użyć polecenia obciążenia, które w smaku MS baz danych SQL o nazwie BULK INSERT

na przykład:

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

odniesienie składnia jest następująca:

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' ] 
    )] 
+3

Osoby zainteresowane wykonaniem BULK INSERT na SQL Server za pośrednictwem Pythona mogą również zainteresować się [moją odpowiedzią na powiązane pytanie] (http://stackoverflow.com/a/29649340/2144390). –