2013-08-07 12 views
17

Ho problemi a eseguire query su una tabella di> 5 milioni di record dal mio database MS SQL Server. Voglio essere in grado di selezionare tutti i record, ma il mio codice sembra fallire quando si selezionano molti dati in memoria.Come creare un grande dataframe panda da una query sql senza esaurire la memoria?

Questo funziona:

import pandas.io.sql as psql 
sql = "SELECT TOP 1000000 * FROM MyTable" 
data = psql.read_frame(sql, cnxn) 

... ma questo non funziona:

sql = "SELECT TOP 2000000 * FROM MyTable" 
data = psql.read_frame(sql, cnxn) 

Esso restituisce questo errore:

File "inference.pyx", line 931, in pandas.lib.to_object_array_tuples 
(pandas\lib.c:42733) Memory Error 

Ho letto here che un problema simile esiste quando si crea un dataframe da un file csv, e che la soluzione è usare "iterator" e "chunksi" parametri ze' come questo:

read_csv('exp4326.csv', iterator=True, chunksize=1000) 

C'è una soluzione simile per l'esecuzione di query da un database SQL? In caso contrario, qual è il work-around preferito? Devo leggere i record in blocchi con qualche altro metodo? Ho letto un po 'di discussione su here per lavorare con dataset di grandi dimensioni in panda, ma sembra che ci sia un sacco di lavoro per eseguire una query SELECT *. Sicuramente c'è un approccio più semplice.

+0

Quanta memoria si fa avere? –

+0

@PhillipCloud la mia macchina ha 4 GB di RAM. – slizb

+0

A seconda del 'dtype' delle tue colonne e del numero di colonne puoi facilmente raggiungere 4 GB. Ad esempio, –

risposta

18

Aggiornamento: assicurarsi di controllare la risposta di seguito, poiché Pandas dispone ora del supporto integrato per il caricamento in blocco.

Si potrebbe semplicemente provare a leggere la tabella di input chunk-saggio e assemblare il dataframe pienamente dei singoli pezzi in seguito, in questo modo:

import pandas as pd 
import pandas.io.sql as psql 
chunk_size = 10000 
offset = 0 
dfs = [] 
while True: 
    sql = "SELECT * FROM MyTable limit %d offset %d order by ID" % (chunk_size,offset) 
    dfs.append(psql.read_frame(sql, cnxn)) 
    offset += chunk_size 
    if len(dfs[-1]) < chunk_size: 
    break 
full_df = pd.concat(dfs) 

Potrebbe anche essere possibile che l'intera dataframe è semplicemente troppo grande per adattarsi alla memoria, in tal caso non avrai altra scelta che limitare il numero di righe o colonne che stai selezionando.

+0

-Grazie, ci proverò, anche se temo che lo spazio di memoria possa effettivamente essere il mio problema. Inoltre, poiché utilizzo MS SQL-Server2008, le opzioni SQL LIMIT e OFFSET non sono disponibili. Altri dovrebbero sapere di fare riferimento [qui] (http://stackoverflow.com/questions/187998/row-offset-in-sql-server) per la soluzione specifica per la loro configurazione – slizb

+2

puoi anche scrivere questi df in un file HDF5 (la domanda a cui hai fatto riferimento usa quello, anche consulta documenti, aggiungendo le tabelle: http://pandas.pydata.org/pandas-docs/dev/io.html#hdf5-pytables. Quindi leggi di nuovo (sezioni, o itera in base alle necessità) ; HDF5 molto più compatto di SQL per i dati – Jeff

1

una soluzione di base alla mia domanda: avere più memoria:

La mia azienda ha un computer ad alte prestazioni con 64 GB di RAM (16x che sulla mia macchina). Ho provato a fare remoting su questa macchina e ad eseguirne il codice. Con mia grande gioia, ha funzionato senza errori di memoria!

Questa soluzione non è una soluzione valida per tutti coloro che hanno questo problema di memoria, ma se si dispone dell'opzione può portare a termine il lavoro.

HDF5 sembra il modo migliore per ottenere una soluzione più permanente come descritto da @Jeff.

20

Come menzionato in un commento, a partire da panda 0,15, si ha un'opzione di chunksize in read_sql per leggere ed elaborare il pezzo query pezzo:

sql = "SELECT * FROM My_Table" 
for chunk in pd.read_sql_query(sql , engine, chunksize=5): 
    print(chunk) 

Riferimento: http://pandas.pydata.org/pandas-docs/version/0.15.2/io.html#querying

+0

** Questo è il modo ** per gestire i problemi in cui la dimensione della RAM zelusp

+1

è possibile saltare la lettura di alcuni blocchi? – denfromufa

+0

Ad esempio un argomento di parole chiave skip_chunks = number_of_chunks, che può salta prima alcuni blocchi senza nemmeno leggerli.Il caso d'uso sta leggendo la fine o il centro della tabella SQL con oltre 1 milione di righe senza ricorrere alla query SQL o SQLalchemy. – denfromufa

Problemi correlati