Mysql
 sql >> Database >  >> RDS >> Mysql

Il modo più veloce per leggere un'enorme tabella MySQL in Python

Un'altra opzione potrebbe essere quella di utilizzare il multiprocessing modulo, dividendo la query e inviandola a più processi paralleli, quindi concatenando i risultati.

Senza sapere molto sui pandas chunking - Penso che dovresti eseguire il chunking manualmente (che dipende dai dati)... Non usare LIMIT / OFFSET - le prestazioni sarebbero terribili.

Questa potrebbe non essere una buona idea, a seconda dei dati. Se esiste un modo utile per suddividere la query (ad esempio se si tratta di una serie temporale o se esiste una sorta di colonna di indice appropriata da utilizzare, potrebbe avere senso). Ho inserito due esempi di seguito per mostrare casi diversi.

Esempio 1

import pandas as pd
import MySQLdb

def worker(y):
    #where y is value in an indexed column, e.g. a category
    connection = MySQLdb.connect(user='xxx', password='xxx', database='xxx', host='xxx')
    query = "SELECT * FROM example_table WHERE col_x = {0}".format(y)
    return pd.read_sql(query, connection)

p = multiprocessing.Pool(processes=10) 
#(or however many process you want to allocate)

data = p.map(worker, [y for y in col_x_categories])
#assuming there is a reasonable number of categories in an indexed col_x

p.close()
results = pd.concat(data) 

Esempio 2

import pandas as pd
import MySQLdb
import datetime

def worker(a,b):
    #where a and b are timestamps
    connection = MySQLdb.connect(user='xxx', password='xxx', database='xxx', host='xxx')
    query = "SELECT * FROM example_table WHERE x >= {0} AND x < {1}".format(a,b)
    return pd.read_sql(query, connection)

p = multiprocessing.Pool(processes=10) 
#(or however many process you want to allocate)

date_range = pd.date_range(start=d1, end=d2, freq="A-JAN")
# this arbitrary here, and will depend on your data /knowing your data before hand (ie. d1, d2 and an appropriate freq to use)

date_pairs = list(zip(date_range, date_range[1:]))
data = p.map(worker, date_pairs)

p.close()
results = pd.concat(data)

Probabilmente modi più carini per farlo (e non sono stati testati correttamente ecc.). Interessati a sapere come va se lo provi.