У меня есть код, который вставляет некоторые данные в мою базу данных из файла csv. Сейчас он работает довольно медленно. Я смотрел в другом месте, и казалось, что использование COPY может помочь ускорить мои вставки, но (как вы можете видеть ниже) мне иногда нужно обновить db, так как я не хочу дубликатов. Кроме того, почти все данные основаны на подзапросах SELECT. Вот соответствующая часть моего кода:Как эффективно вставлять и обновлять данные в базу данных с помощью psychopg2?
def insert_values(self):
read_dict=self.my_csv_reader.main_row_dict
for key in read_dict:
for row_index in range(1, len(read_dict[key])):
if read_dict[key][row_index]==None or read_dict[key][row_index]=="" or read_dict[key][row_index]==" ":
continue
else:
self.cur.execute(self.build_sub_select_query(self.ID, "wf_variable", "name = " + "'" + self.get_header_value(row_index) + "'"))
wf_variable_id=self.cur.fetchall()[self.QUERY_LIST_INDEX][self.QUERY_TUPLE_INDEX]
self.cur.execute(self.build_sub_select_query(self.ID, "point", "guid =" + "'" + read_dict[key][0] + "'"))
point_id =self.cur.fetchall()[self.QUERY_LIST_INDEX][self.QUERY_TUPLE_INDEX]
self.cur.execute(self.build_sub_select_query("point."+self.ID,"point join point_data on point.id=point_data.point_id","point.id = " + str(point_id) +" and wf_variable_id = "+ str(wf_variable_id)))
id_count = len(self.cur.fetchall()[0])
if id_count==0:
sql_code = "INSERT INTO " + self.TABLE + "(value, point_id, wf_variable_id) VALUES " + " (%s,%s,%s)"
self.cur.execute(sql_code,(read_dict[key][row_index],point_id,wf_variable_id))
elif id_count==1:
sql_code = "UPDATE " + self.TABLE + " set " + "value=%s where point_id=%s and wf_variable_id =%s"
self.cur.execute(sql_code, (read_dict[key][row_index], point_id, wf_variable_id))
else:
Exception("The point with id, "+point_id+" has more than one parent level attribute. This should be investigated.")
Я задаюсь быстрый способ вставки/обновления данных из моего файла CSV. Должен ли я сначала запускать все мои подзапросы и хранить результаты в структуре данных? Точно так же, как только я узнаю, должен ли запрос быть вставкой и обновлением, я должен хранить их отдельно и запускать их с помощью функции executeemany(), вместо того, чтобы использовать execute повторно или я неправильно понимаю цель executeemany? Как замечание, я понимаю, что есть другие улучшения, которые я мог бы внести в код, например, разбить вставку и обновление на отдельные функции, и я буду реорганизовать, как только я получу эту работу, но сейчас я просто пытаюсь обратиться к вопрос скорости.
Последнее замечание, я реорганизовал цикл так, чтобы он пересекал все, что мне нужно, чтобы выбрать в моем csv и кормить его в кортеж. Затем я выбрал все это сразу, а не один за другим. Это значительно улучшило производительность. Например, при одном тестовом прогоне в 500 строк потребовалось около 30 секунд, чтобы выполнить один большой запрос, в отличие от примерно 0,5 секунды на небольшой запрос (всего 250 секунд или примерно 8 раз больше времени). Снова урок что минимизация запросов является ключом к ускорению сценариев, использующих psychopg. –