#python #performance #csv
#python #Производительность #csv
Вопрос:
Я использую простой скрипт для извлечения данных из Oracle DB и записи данных в CSV-файл с помощью CSV writer.
Таблица, к которой я запрашиваю, содержит около 25 тысяч записей, скрипт работает отлично, за исключением того, что он на самом деле очень медленный. Для завершения требуется 25 минут.
Каким образом я мог бы ускорить это, изменив код? Любые советы от вас, героев, приветствуются.
#
# Load libraries
#
from __future__ import print_function
import cx_Oracle
import time
import csv
#
# Connect to Oracle and select the proper data
#
con = cx_Oracle.connect('secret')
cursor = con.cursor()
sql = "select * from table"
#
# Determine how and where the filename is created
#
path = ("c:\path\")
filename = time.strftime("%Y%m%d-%H%M%S")
extentionname = (".csv")
csv_file = open(path filename extentionname, "w")
writer = csv.writer(csv_file, delimiter=',', lineterminator="n",
quoting=csv.QUOTE_NONNUMERIC)
r = cursor.execute(sql)
for row in cursor:
writer.writerow(row)
cursor.close()
con.close()
csv_file.close()
Комментарии:
1. Если вы используете простой csv, возможно, быстрее подготовить схему в памяти и сбросить ее в файл?
2. «Для завершения требуется 25 минут». : Как вы можете быть уверены, что большую часть времени тратит
for row ... writer.writerrow(...
3. Прежде чем изменять код, я бы вставил туда несколько простых
print(time.time())
вызовов, чтобы посмотреть, что занимает так много времени. Кроме того, протестируйте запуск скрипта только для чтения из базы данных, фактически ничего не записывая. Возможно, ваше подключение к базе данных просто по какой-то причине происходит очень медленно.4. Маловероятно, что csv.writer. Первым делом я бы проверил, действительно ли «таблица» является таблицей, а не представлением. Oracle оптимизирует запрос для получения первых 500 строк (при условии, что вы используете SQL developer для тестирования SELECT). Или, возможно, таблица очень широкая, что означает, что вы загружаете и записываете много данных в строку — даже если это всего 25 КБ.
5. Сообщалось, что настройка
extrasaction='ignore'
значительно ускоряет процесс. Я лично не видел этого улучшения, но, возможно, это работает для некоторых вариантов использования?
Ответ №1:
Вы пробовали использовать writerows
функцию из модуля csv? Вместо записи каждой записи по одной, это дает возможность записывать все сразу. Это должно ускорить работу.
data = [] #data rows
with open('csv_file.csv', 'w') as csv_file:
writer = csv.DictWriter(csv_file)
writer.writeheader()
writer.writerows(data)
Кроме того, вы также можете использовать модуль pandas для записи большого объема данных в файл CSV. Этот метод объясняется на примерах здесь.
Комментарии:
1. Почему
writerows
было бы быстрее? Узкое место, скорее всего, в части «запись на диск», поскольку ввод-вывод файлов выполняется намного медленнее, чем другие операции2. Вы правы в том, что операции ввода-вывода файлов могут быть узким местом при записи данных на диск, и это может быть оптимизировано с помощью
writerows()
сравнения сwriterow()
.writerows()
может снизить накладные расходы на операции ввода-вывода файлов, позволяя вам записывать несколько строк в файл за одну операцию. При использованииwriterow()
каждый вызов функции открывается и записывается в файл.3. Могу ли я получить источник для этого? AFAIK файл остается открытым до тех пор, пока у вас есть дескриптор файла, возвращаемый
open