Я подозреваю, что для обновления 100 000 строк, как это, большую часть времени занимает создание дополнительных кортежей и вставка их в таблицу или добавление их в таблицу, а не поиск предыдущего кортежа, чтобы пометить его как удаленный.

отрим два следующих примера кода Python, которые достигают того же, но со значительной и удивительной разницей в производительности.

import psycopg2, time

conn = psycopg2.connect("dbname=mydatabase user=postgres")
cur = conn.cursor('cursor_unique_name')  
cur2 = conn.cursor()

startTime = time.clock()
cur.execute("SELECT * FROM test for update;")
print ("Finished: SELECT * FROM test for update;: " + str(time.clock() - startTime));
for i in range (100000):
    cur.fetchone()
    cur2.execute("update test set num = num + 1 where current of cursor_unique_name;")
print ("Finished: update starting commit: " + str(time.clock() - startTime));
conn.commit()
print ("Finished: update : " + str(time.clock() - startTime));

cur2.close()
conn.close()

А также:

import psycopg2, time

conn = psycopg2.connect("dbname=mydatabase user=postgres")
cur = conn.cursor('cursor_unique_name')  
cur2 = conn.cursor()

startTime = time.clock()
for i in range (100000):
    cur2.execute("update test set num = num + 1 where id = " + str(i) + ";")
print ("Finished: update starting commit: " + str(time.clock() - startTime));
conn.commit()
print ("Finished: update : " + str(time.clock() - startTime));

cur2.close()
conn.close()

Оператор create для проверки таблицы:

CREATE TABLE test (id serial PRIMARY KEY, num integer, data varchar);

И эта таблица содержит 100000 строк и VACUUM ANALYZE TEST; был запущен.

Я получил следующие результаты последовательно на нескольких попытках.

Первый пример кода:

Finished: SELECT * FROM test for update;: 0.00609304950429
Finished: update starting commit: 37.3272754429
Finished: update : 37.4449708474

Второй пример кода:

Finished: update starting commit: 24.574401185
Finished committing: 24.7331461431

Это очень удивительно для меня, так как я думаю, что должно быть с точностью до наоборот, а это означает, что обновление с использованием курсора должно быть значительно быстрее в соответствии сэто ответ.

Ответы на вопрос(1)

Решение Вопроса

что тест сбалансирован - ваш первый код извлекает данные из курсора, затем обновляет, тогда как второй обновляет данные вслепую по идентификатору без извлечения данных. Я предполагаю, что первая последовательность кода преобразуется в команду FETCH, за которой следует UPDATE, так что это два обхода команды клиент / сервер, а не один.

(Кроме того, первый код начинается с блокировки каждой строки в таблице - это вытягивает всю таблицу в буферный кеш - хотя, подумав об этом, я сомневаюсь, что это на самом деле влияет на производительность, но вы не упомянули об этом)

Кроме того, я думаю, что для простой таблицы не будет много различий между обновлением с помощью ctid (которое, как я полагаю,where current of... работает) и обновление через первичный ключ - обновление pkey является дополнительным поиском индекса, но если индекс неогромный это не большая часть деградации.

Я подозреваю, что для обновления 100 000 строк, как это, большую часть времени занимает создание дополнительных кортежей и вставка их в таблицу или добавление их в таблицу, а не поиск предыдущего кортежа, чтобы пометить его как удаленный.

Ваш ответ на вопрос