Tamaño de base de datos inicial de PostgreSQL

12

Hay 2 partes en mi pregunta.

  1. ¿Hay alguna forma de especificar el tamaño inicial de una base de datos en PostgreSQL?
  2. Si no lo hay, ¿cómo lidiar con la fragmentación cuando la base de datos crece con el tiempo?

Recientemente migré de MSSQL a Postgres, y una de las cosas que hicimos en el mundo de MSSQL al crear una base de datos fue especificar el tamaño inicial de la base de datos y el registro de transacciones. Esto redujo la fragmentación y aumentó el rendimiento, especialmente si el tamaño "normal" de la base de datos se conoce de antemano.

El rendimiento de mi base de datos disminuye a medida que aumenta el tamaño. Por ejemplo, la carga de trabajo a la que lo someto normalmente toma 10 minutos. A medida que crece la base de datos, esta vez aumenta. Hacer un ANÁLISIS DE VACÍO, VACÍO COMPLETO y VACÍO COMPLETO no parece resolver el problema. Lo que resuelve el problema de rendimiento es detener la base de datos, fragmentar la unidad y luego hacer un ANÁLISIS COMPLETO DE VACÍO para que el rendimiento de mi prueba vuelva a los 10 minutos originales. Esto me lleva a sospechar que la fragmentación es lo que me está causando dolor.

No he podido encontrar ninguna referencia para reservar espacio de tablas / bases de datos en Postgres. O estoy usando la terminología incorrecta y, por lo tanto, no encuentro nada, o hay una forma diferente de mitigar la fragmentación del sistema de archivos en Postgres.

Cualquier puntero?

La solución

Las respuestas proporcionadas ayudaron a confirmar lo que había comenzado a sospechar. PostgreSQL almacena la base de datos en varios archivos y esto es lo que permite que la base de datos crezca sin preocuparse por la fragmentación. El comportamiento predeterminado es empaquetar estos archivos hasta el borde con datos de tabla, lo cual es bueno para tablas que rara vez cambian pero es malo para tablas que se actualizan con frecuencia.

PostgreSQL utiliza MVCC para proporcionar acceso concurrente a los datos de la tabla. Bajo este esquema, cada actualización crea una nueva versión de la fila que se actualizó (esto podría ser a través de la marca de tiempo o el número de versión, ¿quién sabe?). Los datos antiguos no se eliminan de inmediato, sino que se marcan para su eliminación. La eliminación real ocurre cuando se realiza una operación de VACÍO.

¿Cómo se relaciona esto con el factor de relleno? El factor de relleno predeterminado de la tabla de 100 empaqueta completamente las páginas de la tabla, lo que a su vez significa que no hay espacio dentro de la página de la tabla para contener filas actualizadas, es decir, las filas actualizadas se colocarán en una página de tabla diferente de la fila original. Esto es malo para el rendimiento, como lo demuestra mi experiencia. Como mis tablas de resumen se actualizan con mucha frecuencia (hasta 1500 filas / seg), opté por establecer un factor de relleno de 20, es decir, el 20% de la tabla será para datos de fila insertados y el 80% para datos de actualización. Si bien esto puede parecer excesivo, la gran cantidad de espacio reservado para las filas actualizadas significa que las filas actualizadas permanecen dentro de la misma página que la original y que la página de la tabla no está llena cuando se ejecuta el demonio de vacío automático para eliminar las filas obsoletas.

Para "arreglar" mi base de datos, hice lo siguiente.

  1. Establezca el factor de relleno de mis tablas de resumen en 20. Puede hacerlo en el momento de la creación pasando un parámetro a CREATE TABLE o después del hecho a través de ALTER TABLE. Emití el siguiente comando plpgsql:ALTER TABLE "my_summary_table" SET (fillfactor = 20);
  2. Emitió un VACÍO COMPLETO, ya que esto escribe una versión completamente nueva del archivo de la tabla y por lo tanto, por implicación, escribe un nuevo archivo de la tabla con el nuevo factor de relleno .

Al volver a ejecutar mis pruebas, no veo una degradación del rendimiento incluso cuando la base de datos es tan grande como necesito que sea con muchos millones de filas.

TL; DR: la fragmentación del archivo no fue la causa, fue la fragmentación del espacio de tablas. Esto se mitiga ajustando el factor de relleno de la tabla para adaptarlo a su caso de uso particular.

CadentOrange
fuente
Dudo que sea la operación de cambio de tamaño de archivo. Mi conjetura es que mantener los índices es lo que ralentiza las inserciones. Hay una discusión actual sobre la lista de correo de PG con respecto a esto (aunque sin una solución): postgresql.1045698.n5.nabble.com/…
a_horse_with_no_name

Respuestas:

4
  1. No es lo único cercano a eso cuando compilas el servidor con el conmutador --with-segsize, esto podría ayudar si tu mesa está ocupando más espacio que un concierto y tu sistema de archivos puede manejar un solo archivo sobre un concierto. Si está insertando 20 conciertos, tendrá que crear 20 archivos si no usa este interruptor. Si su sistema de archivos puede manejar un archivo a través de un concierto, puede configurarlo en un valor grande, lo más probable es que vea algún beneficio, en el peor de los casos, un pequeño beneficio.

  2. Eche un vistazo a CLUSTER http://www.postgresql.org/docs/9.1/static/sql-cluster.html y FILLFACTOR http://www.postgresql.org/docs/9.1/static/sql-createtable.html , http://www.postgresql.org/docs/9.1/static/sql-createindex.html

Tenga en cuenta que FILLFACTOR puede aplicarse tanto a tablas como a índices.

Kuberchaun
fuente
5

Hay otra cosa en juego que aún no ha entrado en sus ecuaciones: actualización CALIENTE . Respuestas relacionadas:

Ajuste FILLFACTORa un precio tan bajo como 20 no parece excesivo. Infla la mesa hasta cinco veces su tamaño. Si las actualizaciones HOT funcionan, no debería tener que ir tan bajo, normalmente .

Hay excepciones: las actualizaciones HOT solo pueden reutilizar tuplas muertas de transacciones anteriores , no de las mismas o concurrentes . Por lo tanto, una gran carga concurrente o transacciones largas que actualizan repetidamente las mismas filas pueden garantizar una configuración tan baja (o incluso más baja).

Si tiene grandes actualizaciones, cambiando grandes porciones de la tabla a la vez, es posible que desee dividirlas en un par de fragmentos, idealmente solo cambiando tantas filas a la vez como se ajuste localmente en la página de datos. Pero eso es difícil de estimar y regular.

Tenga en cuenta que las actualizaciones HOT solo funcionan cuando las columnas modificadas no están involucradas en los índices de ninguna manera (ni como datos ni como condición en un índice parcial). Es posible que esté bloqueando actualizaciones CALIENTES con índices en columnas actualizadas. Si esos son prescindibles, puede obtener un mejor rendimiento general sin ellos.

Finalmente, puede establecer parámetros de autovacuum por tabla . Puede apuntar a tablas muy actualizadas con configuraciones agresivas que permiten un empaquetado de filas algo más estricto que solo FILLFACTOR 20.

Erwin Brandstetter
fuente
1
Cosas interesantes, lo leeré e intentaré comprender mejor lo que significan las actualizaciones HOT para mi sistema.
CadentOrange
4

Si su problema es la fragmentación de archivos, entonces no, no lo hay. En Postgres, cada tabla obtiene su propio archivo o conjunto de archivos si usa TOAST en el sistema de archivos. Esto difiere de, por ejemplo, Oracle (o aparentemente MS-SQL) donde crea archivos de espacio de tabla de tamaño predeterminado para colocar sus tablas, aunque incluso allí podría tener problemas de fragmentación del sistema de archivos si los archivos de espacio de tabla se extienden o el sistema de archivos está mal fragmentado para empezar.

En cuanto a su segunda pregunta ... No tengo idea de cómo lidiar limpiamente con la fragmentación del sistema de archivos, ya que MS-Windows es el único sistema operativo donde he experimentado problemas de fragmentación y no ejecuto MS-Windows más que absolutamente necesita ser estos días. Quizás colocar los archivos de la base de datos en sus propios discos podría mitigarlo hasta cierto punto.

gsiems
fuente
Tenga en cuenta que tiene una fragmentación interna de la base de datos PostgreSQL y una fragmentación externa del sistema de archivos. Interna creo que puede mitigarse con VACÍO y usando CLUSTERS y FILLFACTOR. El sistema de archivos puede manejarse ejecutando una desfragmentación para el sistema de archivos dado. Y los sistemas de archivos Linux / Unix pueden fragmentarse algunas veces dependiendo de la carga de trabajo y el tipo de sistema de archivos.
Kuberchaun
La fragmentación del sistema de archivos no es realmente un gran problema con NTFS hoy en día.
a_horse_with_no_name
1
¿Pensé que NTFS era conocido por eso? Mi máquina de estación de trabajo se fragmenta bastante bien, lo único que la mantiene bajo control es una desfragmentación programada que Windows7 ejecuta a diario.
Kuberchaun