Как сократить время, необходимое для вставки кадра данных в большую таблицу базы данных SQL Server?Python

Программы на Python
Anonymous
Как сократить время, необходимое для вставки кадра данных в большую таблицу базы данных SQL Server?

Сообщение Anonymous »

Обзор
Мне нужно обновить данные в принадлежащей мне базе данных данными, полученными из базы данных сервера Snowflake. Я получаю данные за определенную дату из Snowflake, и мне нужно вставить их в локальную базу данных на эту дату. В настоящее время эта операция занимает 273 секунды, и мне необходимо максимально ее оптимизировать. Все это делается на Python с использованием библиотеки pyodbc для вставки в локальную базу данных и sqlalchemy для получения данных из Snowflake.
Подробный процесс
Я использую cProfile в сочетании со Snakeviz для профилирования и визуализации производительности моей операции, которая выполняется для определенной даты, называемой update_snf. Весь процесс состоит из следующих шагов:
  • Создание соединения и выполнение SQL-запроса для получения данных с сервера Snowflake. Вызовите эту операцию get_data_from_snf. Выполнение этой операции занимает 111 с, причем большую часть (108 с) времени занимает вызов функции Pandas.read_sql(query, Connection). (определено в pandas/io/sql.py), который выполняет запрос и возвращает результат в кадре данных df.
  • Форматирование df, что занимает относительно меньше времени (17,8 с)
  • Вставка форматированного кадра данных df в мою локальную базу данных (вызовите эту функцию Insert_data_into_db) . Эта операция занимает большую часть времени (143 с, из которых 93,1 с занимает метод выполнения объекта pyodbc.Cursor и 43,3 с методом выполнения). Назовем таблицу, в которую происходит эта вставка, table. table – довольно большая таблица, содержащая примерно 150 миллионов кортежей и 130 столбцов.
Я пытаюсь сократить время всей этой операции любым возможным способом, оптимизируя некоторые или даже все шаги. Ожидается, что df будет содержать около 200 000 строк для каждой даты.
Текущая попытка
Довольно простой Python API используются, и многопроцессорность или многопоточность в настоящий момент не используются. Вставка данных в очень большую таблицу занимала неприемлемое количество времени, поэтому в настоящее время используется альтернатива, реализующая вставку_data_into_db следующим образом:
  • Создается новая таблица с именем table_temp (эта таблица уже существует в базе данных; она не создается заново при каждом запуске функции)
  • Код: Выделить всё

    cursor.execute
    используется для выполнения следующего SQL-запроса:

Код: Выделить всё

TRUNCATE TABLE table_temp
DELETE FROM table where Date = {date}
Операция удаления необходима, чтобы гарантировать, что на локальном сервере присутствуют только обновленные записи из Snowflake и нет дублирования. По сути, он удаляет устаревшие данные, прежде чем можно будет вставить свежие данные.
3. df разбивается на фрагменты по 18000 строк, а для курсора.fast_executemany установлено значение True. Теперь мы используем курсор.executemany(insert_query, df_chunk), чтобы вставить каждый из фрагментов (список кортежей) один за другим в table_temp.
4. Теперь мы вставляем всю таблицу table_temp (которая содержит все записи для конкретной даты из Snowflake) в таблицу, используя:

Код: Выделить всё

INSERT INTO table
SELECT * FROM table_temp
Поэтому вместо вставки данных непосредственно в таблицу мы сначала вставляем их частями во временную таблицу, а затем вставляем в таблицу всю временную таблицу. p>
Вопросы в этом текущем подходе:
  • Есть ли какой-либо способ избежать этого подхода к фрагментированию и напрямую вставить в таблицу< /code> что не займет много времени? Похоже, что время, необходимое для этой прямой вставки, увеличивается по мере того, как таблица становится больше, и при текущем размере 150 миллионов строк это занимает слишком много времени.
  • Можем ли мы использовать параллелизм в форме многопроцессорности или многопоточности где-нибудь в этом подходе?
  • Можем ли мы использовать потоковую передачу где-нибудь здесь? Если да, то как?
  • Можем ли мы ускорить извлечение данных из Snowflake в Dataframe в памяти перед вставкой Dataframe в базу данных? Есть ли способ вообще избежать этого?
Я использую Python 3.11 на сервере Windows 8 с использованием SQL Server. Любая оптимизация приветствуется! Спасибо большое!

Подробнее здесь: https://stackoverflow.com/questions/789 ... arge-table

Вернуться в «Python»