¿SELECT elimina las filas muertas como lo hace VACUUM?

9

Estaba jugando VACUUMy noté un comportamiento inesperado en el que SELECTlas filas de una tabla parecen reducir el trabajo que VACUUMtiene que hacer después.

Datos de prueba

Nota: autovacuum está deshabilitado

CREATE TABLE numbers (num bigint);
ALTER TABLE numbers SET (
  autovacuum_enabled = 'f',
  toast.autovacuum_enabled = 'f'
);

INSERT INTO numbers SELECT generate_series(1, 5000);

Prueba 1

Ahora ejecutamos una actualización en todas las filas,

UPDATE numbers SET num = 0;

Y cuando corremos VACUUM (VERBOSE) numbers;tenemos,

INFO:  vacuuming "public.numbers"
INFO:  "numbers": removed 5000 row versions in 23 pages
INFO:  "numbers": found 5000 removable, 5000 nonremovable row versions in 45 out of 45 pages
DETAIL:  0 dead row versions cannot be removed yet, oldest xmin: 6585
There were 0 unused item pointers.

Prueba 2

Ahora emitimos otro UPDATE, pero esta vez agregamos un SELECTdespués,

UPDATE numbers SET num = 1;
SELECT * FROM numbers;

Y cuando corremos VACUUM (VERBOSE) numbers;tenemos,

INFO:  vacuuming "public.numbers"
INFO:  "numbers": removed 56 row versions in 22 pages
INFO:  "numbers": found 56 removable, 5000 nonremovable row versions in 45 out of 45 pages
DETAIL:  0 dead row versions cannot be removed yet, oldest xmin: 6586
There were 56 unused item pointers.

¿Qué está pasando exactamente aquí? ¿Por qué la segunda versión que ejecuto, después de SELECTeliminar las tuplas muertas de las páginas que visita, es bastante similar VACUUM?

Estoy ejecutando Postgres 11.3 en macOS 10.14.5.

rafbm
fuente
2
¿Qué cliente usas para ejecutar tus comandos? ¿Está habilitado el compromiso automático?
mustaccio
2
Voy a eliminar la pregunta "¿La tabla de VACÍO es básicamente SELECCIONAR * DESDE la tabla debajo del capó?" (no lo es) Creo que es un buen seguimiento, la respuesta aquí es simplemente que SELECT puede eliminar filas muertas, y comparte eso en común con VACUUM. La forma en que son diferentes será una conversación muy exhaustiva sobre el rollover XID y muchas otras cosas. Esa pregunta es básicamente "¿Qué otras cosas hace el vacío además de eliminar las filas muertas"? (Lo cual sería un poco vago)
Evan Carroll
@mustaccio Hice estas pruebas con un script Ruby usando ActiveRecord, que usa la gema PG debajo del capó. Creo que la confirmación automática está habilitada de forma predeterminada, ya que no necesita emitir ningún COMPROMISO a menos que BEGIN se use explícitamente.
rafbm

Respuestas:

5

De esta publicación en / r / PostgreSQL a una respuesta de Laurenz Albe parece que las actualizaciones de Heup Only Tuples (HOT) pueden ser responsables. De la descripción de actualizaciones CALIENTES ensrc/backend/access/heap/README.HOT

Efectivamente, la recuperación de espacio ocurre durante la recuperación de tuplas cuando la página está casi llena (<10% libre) y se puede adquirir un bloqueo de limpieza de búfer. Esto significa que UPDATE, DELETEy SELECTpuede activar la recuperación de espacio, pero a menudo no durante INSERT ... VALUESporque no recupera una fila.

La cita no está en la respuesta original, pero el resto es una cita,

Para apoyar o refutar esta teoría, ejecute la siguiente consulta:

SELECT n_tup_upd, n_tup_hot_upd
FROM pg_stat_user_tables
WHERE schemaname = 'public' AND relname = 'TABLE_NAME';

Si n_tup_hot_updes mayor que cero, tenemos un caso.

Evan Carroll
fuente
Ahora estamos hablando. +1
mustaccio
HOT parece ser una buena explicación. Si I CREATE INDEX idx_numbers ON numbers USING btree (num), la salida de VACÍO cambia a INFO: "numbers": removed 5000 row versions in 45 pages. Sin embargo, n_tup_hot_updtenga en cuenta que en el escenario sin índice, siempre es 0, tanto entre UPDATE y SELECT como entre SELECT y VACUUM. También me aseguré de ejecutar SELECT pg_sleep(10)entre cada declaración para que las estadísticas estén actualizadas (veo seq_scan: 2, una para la ACTUALIZACIÓN y otra para la SELECCIONAR).
rafbm
¿El select genera WAL en este caso? Tenía la impresión de que las selecciones no generan WAL en absoluto. En caso afirmativo, esto significaría que la eliminación de filas muertas se propaga a cualquier esclavo. Si no, esto significa que todavía es necesario pasar la aspiradora en el esclavo. También significaría que los amos y los esclavos no son idénticos. Hmm, tal vez necesito investigar un poco y publicar una pregunta y / o respuesta o dos.
Colin 't Hart
1

En el caso especial de una tabla no indexada, sí, SELECT puede hacer el mismo trabajo que VACUUM (en lo que respecta a eliminar filas muertas).

jjanes
fuente
3
¿Podría agregar una explicación?
Laurenz Albe