Мне нужно написать скрипт, который берет набор строк из БД PostgreSQL, вычисляет несколько значений для каждой строки и переносит результаты обратно в БД (существующую таблицу).Есть сложность - мне нужно иметь возможность программно управлять именами таблиц и столбцов.
Мое текущее решение выглядит так:
import psycopg2
from psycopg2.extensions import AsIs, quote_ident
import psycopg2.extras
def upsert_estimated_values(con, table_name, timestamps, column_names, value_list, page_size=1000):
# con is a psycopg2 connection
# timestamps is a list of timestamps (which are the index in the DB table)
# column_names is a list of columns in the DB
# value_list is a list of tuples where each tuple
# contains a value for every column in column_names
sql = 'INSERT INTO %s (timestamp_utc, ' + ', '.join('%s' for _ in range(len(column_names))) \
+ ')\n VALUES (%s, ' + ', '.join('%s' for _ in range(len(column_names))) \
+ ')\nON CONFLICT (timestamp_utc) DO UPDATE\n SET ' \
+ ', '.join('%s = %s' for _ in range(len(column_names))) \
+ ';'
with con.cursor() as cur:
tbl = AsIs(quote_ident(table_name, cur))
cols = [AsIs(quote_ident(col, cur)) for col in column_names]
data = []
for vs, ts in zip(value_list, timestamps):
data.append((
tbl,
*cols,
ts,
*vs,
*itertools.chain(*zip(cols, vs))
))
psycopg2.extras.execute_batch(
cur, sql, page_size=page_size, argslist=data
)
con.commit()
Насколько я понимаю psycopg2
функция execute_batch
создает одну длинную инструкцию SQL для минимизации связи с БД.Но что происходит в этом конкретном случае?Я передаю имя таблицы и имена столбцов в каждой записи argslist
, и я не уверен, что это хорошая идея.
В настоящее время этот переход занимает примерно в 8 раз больше времени, чем получение данных из БД.Любые советы?