pandas read_sql необычайно медленный

#python #mysql #pandas

#python #mysql #pandas

Вопрос:

Я пытаюсь прочитать несколько столбцов из трех разных таблиц MySQL в три разных фрейма данных.

Чтение из базы данных не занимает много времени, но на самом деле помещение их в dataframe происходит довольно медленно.

 start_time = time.time()
print('Reading data from database...')

from sqlalchemy import create_engine
q_crash = 'SELECT <query string> FROM table1'
q_vehicle = 'SELECT <query string> table2'
q_person = 'SELECT <query string> FROM table3'
engine = create_engine('mysql pymysql://user:password@host:port/dbasename')

print('Database time: {:.1f}'.format(time.time() - start_time))

crash = pd.read_sql_query(q_crash, engine)
print('Read_sql time for table 1: {:.1f}'.format(time.time() - start_time))
vehicle = pd.read_sql_query(q_vehicle, engine)
print('Read_sql time for table 2: {:.1f}'.format(time.time() - start_time))
person = pd.read_sql_query(q_person, engine)
print('Read_sql time for table 3: {:.1f}'.format(time.time() - start_time))
 

Вывод:

 Reading data from database...
Database time: 0.0
Read_sql time for table 1: 13.4
Read_sql time for table 2: 30.9
Read_sql time for table 3: 49.4
 

Это нормально? Таблицы довольно большие — таблица 3 содержит более 601 000 строк. Но pandas без проблем обрабатывает большие наборы данных всякий раз, когда я использую read_csv.

Комментарии:

1. Вы читаете из таблиц или представлений?

2. Сколько времени занимают запросы, когда вы запускаете их из командной строки или из какого-либо инструмента, такого как MySQL workbench (работающего на том же компьютере, на котором установлен ваш скрипт Python)?

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

4. Можете ли вы указать, какой клиент вы используете в командной строке? Потому что, если я выполняю запрос select из программы mysql командной строки, для печати 600 000 строк требуется довольно много времени. И если вы выполняете запрос select в рабочей среде MySQL, по умолчанию извлекается максимум 2000 строк.

5. ОК. Это имеет больше смысла, потому что я также использую программу командной строки mysql, но я допустил ошибку и случайно включил LIMIT = 20; в конце запроса (копирование / вставка из более раннего запроса), так что, вероятно, поэтому это было так быстро. Когда я удалил оператор LIMIT, он резко замедлился.

Ответ №1:

pandas.read_sql может быть медленным при загрузке большого набора результатов. В этом случае вы можете попробовать наш инструмент ConnectorX ( pip install -U connectorx ). Мы предоставляем read_sql функциональность и стремимся повысить производительность как по скорости, так и по использованию памяти.

В вашем примере вы можете переключиться на него следующим образом:

 import connectorx as cx

start_time = time.time()

q_crash = 'SELECT <query string> FROM table1'
q_vehicle = 'SELECT <query string> table2'
q_person = 'SELECT <query string> FROM table3'
db_url = "mysql://user:password@host:port/dbasename"

crash = cx.read_sql(q_crash, db_url)
print('Read_sql time for table 1: {:.1f}'.format(time.time() - start_time))
vehicle = cx.read_sql(q_vehicle, db_url)
print('Read_sql time for table 2: {:.1f}'.format(time.time() - start_time))
person = cx.read_sql(q_person, db_url)
print('Read_sql time for table 3: {:.1f}'.format(time.time() - start_time))

 

Кроме того, вы можете использовать многоядерность на своем клиентском компьютере, указав столбец раздела ( partition_on ) и номер раздела ( partition_num ), в которых ConnectorX будет разделен исходный запрос и получен результат каждого разделения параллельно. Вы можете найти несколько примеров того, как это сделать, здесь .

Это наш результат тестирования с использованием 4 потоков в MySQL, извлекающих 60 миллионов строк x 16 столбцов данных:

время mysql
память mysql

Ответ №2:

IMO не имеет особого смысла читать полные таблицы в Pandas DFs, если они у вас есть в MySQL DB — почему бы вам не использовать SQL для фильтрации и объединения ваших данных? Вам действительно нужны все строки из этих трех таблиц как Pandas DFs?

Если вы хотите присоединиться к ним, вы можете сделать это сначала на стороне MySQL и загрузить результирующий набор в один DF…

что-то похожее на:

 qry = 'select p.*, v.*, c.* from vehicle v join person p on v.id = p.vehicle_id join crash c on c.id = p.crash_id where <additional where clause>'
df = pd.read_sql(qry, engine)
 

Комментарии:

1. на самом деле не отвечает на вопрос

2. Я проголосовал за этот комментарий, но я чувствую себя плохо из-за этого. Ответ вполне может быть правильным, пытаться быть полезным в SO может быть сложно, многие люди используют инструмент, который они знают, вместо подходящего инструмента для работы, и может быть трудно быть полезным «, Я попросил помощи о том, как сделать траншею ложкой, я неспросите об использовании «трактора » или что бы это ни было «.