#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 столбцов данных:
Ответ №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 может быть сложно, многие люди используют инструмент, который они знают, вместо подходящего инструмента для работы, и может быть трудно быть полезным «, Я попросил помощи о том, как сделать траншею ложкой, я неспросите об использовании «трактора » или что бы это ни было «.