Время ожидания pandas .to_sql с RDS

У меня есть файл .csv с 22 миллионами строк (~ 850 МБ), который я пытаюсь загрузить в базу данных postgres на Amazon RDS. Это происходит каждый раз (я получаю сообщение об ошибке тайм-аута), даже когда я разбиваю файл на более мелкие части (каждая из 100 000 строк) и даже когда я использую chunksize.

Все, что я делаю на данный момент, это загружаю .csv в качестве фрейма данных, а затем записываю его в БД, используя df.to_sql(table_name, engine, index=False, if_exists='append', chunksize=1000)

Я использую create_engine из sqlalchemy для создания соединения: engine = create_engine('postgresql:database_info')

Я протестировал запись небольших объемов данных с помощью psycopg2 без проблем, но для записи 1000 строк требуется около 50 секунд. Очевидно, что для 22-метровых рядов это не сработает.

Есть ли что-нибудь еще, что я могу попробовать?


person e h    schedule 17.05.2015    source источник
comment
Если вы просто хотите импортировать файл csv в базу данных, вам, вероятно, лучше использовать команду postgresql COPY, поэтому вам не нужен обратный путь к объектам python (что делает его медленнее).   -  person joris    schedule 17.05.2015
comment
Кроме того, какой драйвер вы используете? (psycopg2 ?) Поскольку 50 с для 1000 строк намного медленнее, чем то, что я испытываю с базой данных postgres. Так что, возможно, это также частично медленное соединение с базой данных.   -  person joris    schedule 17.05.2015
comment
спасибо за комментарий, я пробовал использовать psycopg2. Я обновлю вопрос.   -  person e h    schedule 17.05.2015
comment
Вы пробовали COPY подход? Если вы не хотите использовать команды SQL, но остаетесь в Python, вы можете взглянуть на odo, который использует скрытую команду COPY для передачи данных из CSV в SQL: odo.readthedocs.org/en/latest/index.html   -  person joris    schedule 17.05.2015
comment
Для AWS Postgres RDS вам понадобится команда psql/copy, см. здесь: stackoverflow.com/questions/46969474/   -  person RobinL    schedule 31.10.2017


Ответы (2)


Метод pandas DataFrame.to_sql() является не предназначен специально для больших вставок, так как не использует PostgreSQL COPY. Обычные SQL-запросы могут истечь по времени, это не вина pandas, они контролируются сервером базы данных, но могут быть изменены для каждого соединения, см. эта страница и найдите 'statement_timeout'.

Я бы порекомендовал вам рассмотреть возможность использования Redshift, который оптимизирован для хранения данных и может считывать огромные дампы данных непосредственно из корзин S3, используя Копировать с красным смещением.

Если вы не в состоянии использовать Redshift, я бы порекомендовал найти способ выполнить эту операцию с помощью PostgreSQL COPY, так как она была придумана именно для того, чтобы обойти проблему, с которой вы столкнулись.

person firelynx    schedule 18.05.2015
comment
Хорошо, так что просто для ясности, я должен сбросить свои данные в корзину S3, а затем использовать PostgreSQL COPY, верно? - person e h; 18.05.2015
comment
Да, если команда PostgreSQL COPY позволяет указать корзину s3 для чтения в той версии PostgreSQL, которую вы используете в RDS. Redshift это позволяет, и поскольку они очень тесно связаны, это должно работать. - person firelynx; 18.05.2015

Вы можете записать кадр данных в cString, а затем записать его в базу данных, используя метод copy_from в Psycopg, который, как я полагаю, реализует команду COPY PostgreSql, о которой упоминает @firelynx.

import cStringIO
dboutput = cStringIO.StringIO()
output = output.T.to_dict().values()   
dboutput.write('\n'.join([ ''.join([row['1_str'],'\t',
                                    row['2_str'], '\t',
                                    str(row['3_float'])
                                    ])   for row in output]))
dboutput.seek(0)
cursor.copy_from(dboutput, 'TABLE_NAME')
connenction.commit()

где вывод изначально представляет собой кадр данных pandas со столбцами [1_str, 2_str, 3_float], которые вы хотите записать в базу данных.

person RoachLord    schedule 01.09.2016