Команда CLUSTER postgresql не удаляет мертвые кортежи - PullRequest
2 голосов
/ 14 января 2011

У нас есть фоновый процесс (демон linux в бесконечном цикле), который автоматически берет все строки из CSV-файлов, которые находятся в определенном каталоге, и импортирует их в таблицу.Демон обрабатывает любые файлы, которые появляются в каталоге один за другим, написан на python и использует psycopg2 для подключения к нашей базе данных postgresql.

Этот процесс импортирует эти записи с помощью операторов INSERT, но сначала УДАЛЯЕТ любые записи таблицыкоторые имеют тот же уникальный ключ, что и любая из записей в CSV-файле.Обычно процесс УДАЛЯЕТ запись для каждой записи, которую она ВСТАВЛЯЕТ.Так как этот демон работает в фоновом режиме, он удаляет, а затем вставляет строки.Каждый раз, когда он обрабатывает один файл, он специально фиксирует транзакцию, закрывает курсор и затем закрывает соединение.

Периодически (два раза в день) мы хотим запустить CLUSTER, чтобы удалить мертвые кортежи и сохранить таблицу вуправляемый по размеру диска.

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

Если мы остановим процесс, а затемзапустите CLUSTER, размер таблицы на диске резко уменьшится, и pg_stat_user_tables сообщит, что все мертвые кортежи пропали.

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

Также странно, что если мы остановим процесс, затем запустим процесс снова, затем сделаем CLUSTER, он удалит все мертвые кортежи, созданные при предыдущем запуске процесса демона;но любые последующие вызовы CLUSTER не будут очищать любые мертвые кортежи, созданные при текущем запуске процесса демона (пока он, конечно, еще выполняется).

Итак что-то поддерживает какую-то связь с мертвыми кортежами до тех пор, пока процесс не будет остановлен, даже если мы зафиксировали транзакцию и закрыли все соединения с postgres, которые создали эти мертвые кортежи.pg_locks не сообщает ни об открытых блокировках, ни о запущенных транзакциях, поэтому не похоже, что это проблема блокировки или открытой транзакции.

В конце концов, это мешает нам периодически запускать CLUSTERна столе, чтобы он не рос и не рос.

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

while True:
    l = [(get_modified_time(fname), fname) for fname in os.listdir('/tmp/data')]
    l.sort()

    for (t, fname) in l:
        conn = psycopg2.connect("dbname='dbname' user='user' password='password'")
        cursor = conn.cursor()

        # Calls a postgresql function that reads a file and imports it into 
        # a table via INSERT statements and DELETEs any records that have the 
        # same unique key as any of the records in the file.
        cursor.execute("SELECT import('%s', '%s');" % (fname, t))

        conn.commit()
        cursor.close()
        conn.close()

        os.remove(get_full_pathname(fname))

        time.sleep(0.100)

1 Ответ

2 голосов
/ 14 января 2011

Что не так с автовакуумом?Когда autovacuum делает свою работу, вам не нужно использовать CLUSTER для очистки мертвых кортежей.CLUSTER не предназначен для этого, это ВАКУУМ.

Если вы измените процесс на дубликаты ОБНОВЛЕНИЯ, все может стать еще лучше, если вы используете обновления FILLFACTOR: HOT ниже.Они быстрее, освобождают место, сохраняют тот же порядок в хранилище и не требуют ни VACUUM, ни CLUSTER.

...