Самый быстрый способ прочитать огромную таблицу MySQL в Python - PullRequest
0 голосов
/ 03 июля 2018

Я пытался прочитать очень большую таблицу MySQL, состоящую из нескольких миллионов строк. Я использовал Pandas библиотеку и chunks. Смотрите код ниже:

import pandas as pd
import numpy as np
import pymysql.cursors

connection = pymysql.connect(user='xxx', password='xxx', database='xxx', host='xxx')

try:
    with connection.cursor() as cursor:
        query = "SELECT * FROM example_table;"

        chunks=[]

        for chunk in pd.read_sql(query, connection, chunksize = 1000):
            chunks.append(chunk)
        #print(len(chunks))    
        result = pd.concat(chunks, ignore_index=True)
        #print(type(result))
        #print(result)

finally:
    print("Done!")

    connection.close()

На самом деле время выполнения приемлемо, если я ограничу количество строк для выбора. Но если вы хотите выбрать также минимум данных (например, 1 млн строк ), тогда время выполнения значительно увеличивается.

Может быть, есть лучший / более быстрый способ выбора данных из реляционной базы данных в Python?

Ответы [ 3 ]

0 голосов
/ 03 июля 2018

Другим вариантом может быть использование модуля multiprocessing, разделение запроса и его отправка нескольким параллельным процессам, а затем объединение результатов.

Не зная много о pandas разбиении на блоки - я думаю, что вам придется выполнять разбиение вручную (что зависит от данных) ... Не используйте LIMIT / OFFSET - производительность будет ужасной.

Это может быть не очень хорошая идея, в зависимости от данных. Если есть полезный способ разделить запрос (например, если это временная серия или есть какой-то подходящий индексный столбец для использования, это может иметь смысл). Я привел два примера ниже, чтобы показать разные случаи.

Пример 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) 

Пример 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)

Вероятно, более хорошие способы сделать это (и не были должным образом проверены и т. Д.). Интересно узнать, как это происходит, если вы попробуете

0 голосов
/ 23 июля 2019

Для тех, кто использует Windows и не может установить MySQLdb. Я использую этот способ для извлечения данных из огромной таблицы.

import mysql.connector

i = 1
limit = 1000

while True:
    sql = "SELECT * FROM super_table LIMIT {}, {}".format(i, limit)
    cursor.execute(sql)
    rows = self.cursor.fetchall()

    if not len(rows):  # break the loop when no more rows
        print("Done!")
        break

    for row in rows:   # do something with results
        print(row)
0 голосов
/ 03 июля 2018

Вы можете попробовать использовать другой соединитель mysql. Я бы порекомендовал попробовать mysqlclient, который является самым быстрым соединителем mysql (со значительным запасом, я полагаю).

pymysql является чистым клиентом Python для MySQL, тогда как mysqlclient является оболочкой (намного быстрее) библиотек Си.

Использование в основном совпадает с pymsql:

import MySQLdb

connection = MySQLdb.connect(user='xxx', password='xxx', database='xxx', host='xxx')

Подробнее о различных коннекторах читайте здесь: В чем разница между MySQLdb, mysqlclient и MySQL коннектором / Python?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...