Как вставить 1 миллион строк в базу данных Oracle с помощью Python?

#python #database #oracle #insert #oracle18c

#python #База данных #Oracle #вставить #oracle18c

Вопрос:

У меня есть ~ от 100 000 до 1 000 000 строк для вставки в базу данных Oracle18c. Я совсем новичок в Oracle и в таком объеме данных. Я считаю, что должен быть какой-то оптимальный способ сделать это, но пока мне удалось реализовать только построчную вставку:

 def insertLines(connection, table_name, column_names, rows):
    cursor = connection.cursor()
    if table_exists(connection, table_name):
        for row in rows:
            sql = 'INSERT INTO {} ({}) VALUES ({})'.format(table_name, column_names, row)
            cursor.execute(sql)
    cursor.close()
  

Есть ли в Oracle какой-нибудь четкий способ увеличить количество строк для достижения более высокой эффективности с помощью cx_Oracle (библиотека Oracle python)?

РЕДАКТИРОВАТЬ: я прочитал данные из файла CSV.

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

1. как насчет pandas и dataframes?

2. это то, что вы хотите —> cx-oracle.readthedocs.io/en/latest / … также никогда, никогда, никогда не используйте интерполяцию строк при вставке данных

3. @MAhsan К сожалению, я не знаю pandas. Я читаю из CSV-файла, должен ли я сосредоточиться на реализации pandas?

4. Попробовать это не повредит, у этого есть простой в использовании метод read_csv. Затем метод to_sql, для этого требуется настройка движка, для которого вы могли бы использовать cx_Oracle. Конечно, если у вас более 100 тысяч строк, это займет немного времени, но вы могли бы сделать все это за один раз. Вот удобная ссылка для создания подключения к движку gist.github.com/DGrady/7fb5c2214f247dcff2cb5dd99e231483

Ответ №1:

Если ваши данные уже на Python, тогда используйте executemany() . В вашем случае с таким количеством строк вы, вероятно, все равно выполнили бы несколько вызовов для вставки пакетов записей.

Обновление: смотрите документацию cx_Oracle о выполнении пакетной инструкции и массовой загрузке.

Обновление 2: последняя версия cx_Oracle (которая была переименована в python-oracledb) по умолчанию выполняется в «тонком» режиме, который обходит клиентские библиотеки Oracle. Это означает, что во многих случаях загрузка данных выполняется быстрее. Использование и функциональность executemany() в новой версии все те же. Установите что-то вроде python -m pip install oracledb . Вот текущая документация для выполнения пакетной инструкции и массовой загрузки. Также смотрите документацию по обновлению.

Вот пример использования пространства имен python-oracledb. Если вы все еще используете cx_Oracle, измените import на import cx_Oracle as oracledb :

 import oracledb
import csv

...
Connect and open a cursor here...
...

# Predefine the memory areas to match the table definition.
# This can improve performance by avoiding memory reallocations.
# Here, one parameter is passed for each of the columns.
# "None" is used for the ID column, since the size of NUMBER isn't
# variable.  The "25" matches the maximum expected data size for the
# NAME column
cursor.setinputsizes(None, 25)

# Adjust the number of rows to be inserted in each iteration
# to meet your memory and performance requirements
batch_size = 10000

with open('testsp.csv', 'r') as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    sql = "insert into test (id,name) values (:1, :2)"
    data = []
    for line in csv_reader:
        data.append((line[0], line[1]))
        if len(data) % batch_size == 0:
            cursor.executemany(sql, data)
            data = []
    if data:
        cursor.executemany(sql, data)
    con.commit()
  

Как указывали другие:

  • Избегайте использования интерполяции строк в операторах, поскольку это представляет угрозу безопасности. Обычно это также проблема масштабируемости. Используйте переменные привязки. Там, где вам нужно использовать интерполяцию строк для таких вещей, как имена столбцов, убедитесь, что вы сантиментируете любые значения.
  • Если данные уже есть на диске, то использование чего-то вроде SQL * Loader или Data Pump будет лучше, чем чтение их в cx_Oracle и последующая отправка в БД.

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

1. Спасибо за информацию! Я читаю из CSV, и он есть у меня на диске. В чем разница между SQL * Loader и Data Pump?

2. sqlldr считывает данные из CSV-файлов и вставляет их в таблицу. Именно то, что вы хотите. DataPump — это общий термин для утилит expdp и impdp. expdp экспортирует данные и метаданные (по сути, набор команд CREATE и INSERT) и записывает их в собственный двоичный файл. impdp считывает этот двоичный файл и выполняет команды CREATE и INSERT для импорта данных и метаданных в базу данных. Оба полностью документированы на docs.oracle.com/database/121/SUTIL/toc.htm

Ответ №2:

Я не знаю, в каком формате у вас есть данные, но SQL Data Loader — это утилита командной строки, специально созданная для добавления больших объемов данных в Oracle.

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

1. Тогда загрузчик данных, вероятно, был бы лучшим способом загрузки ваших данных.

2. Загрузчик SQL был бы вторым лучшим вариантом

Ответ №3:

Наиболее оптимальным способом с точки зрения производительности и простоты было бы создать внешнюю таблицу поверх вашего CSV-файла, а затем использовать SQL для выполнения вставки.