preloader
  • Inicio
  • PostgreSQL RDS pg-stat-ramdisk-size: Nuevas funcionalidades y sus calculos

blog-thumb

NOTA IMPORTANTE

Esto ya se ha abordado en el núcleo de PostgreSQL, pero esta opción todavía está disponible en RDS.

¿Qué cambia y por qué es tan importante?

El seguimiento de bases de datos y no solo de contadores de tablas de Postgres no es barato, pero desde hace algún tiempo hubo soluciones que implicaba la configuración de un ramdisk para colocar el directorio apuntado por la “stat_temp_directory” variable GUC. Ese directorio colocaba un “global.stat” archivo de estadísticas por base de datos llamado like “db_.stat”. Aunque el mecanismo para escribir en estos archivos evita descargas adicionales o innecesarioas, requiere mucha escritura.

Este cambio no requiere ningún tiempo de inactividad (en instalaciones independientes), ya que una simple recarga obligará a Stat Collector a reescribir los archivos en la carpeta. Hay un blog bastante claro sobre como poner stat_temp_directory en un ramdisk.

El problema se basa en la falta de privilegios de RDS para manipular el contenido de archivos o directorios, lo que no le permite verificar el tamaño actual y establecer un valor adecuado. Aunque, probablemente desee saber que existe un límite de 1 GB para esta configuración en RDS.

Si no desea más detalles y desea activar su almacenamiento, configúrelo en 256 MB y continue con su vida. A pesar de que es una configuración grande (el siguiente parrafo explica por qué), no querrás quedarte corta.

Despúes de aplicar el cambio “pg_stat_ramdisk_size”,verá que la ubicación en el RDS ha cambiado:

show stats_temp_directory;

stats_temp_directory
/rdsdbramdisk/pg_stat_tmp

TL;DR. Cuál es el tamaño esperado de stat_temp_directory?

Antes de seguir adelante, detallemos la estructura de las entradas para el archivo de estadísticas:

Structure/Constant Size
PGSTAT_FILE_FORMAT_ID 1 byte
PgStat_StatTabEntry 164 bytes
PgStat_StatFuncEntry 28 bytes
closingChar ‘E’
describers char (T or F in this case)

En primer lugar, como se explicará más adelante, no todas las tablas, índices y funciones están escritas en el archivo stats de db. Básicamente, una fórmula básica será:

SizeOfDBStatFile = PGSTAT_FILE_FORMAT_ID + describers + (tableCount * PgStat_StatTabEntry) + (funcCount * Pgstat_StatFuncEntry) + closingChar

Para obtener el espacio estimado necesario para las tablas actuales en cada base de datos (tenga en cuenta que esto considera todas la tablas descargadas en el archivo), hay una consulta que puede ejecutar de manera segura en cada base de datos en su instancia de PostgreSQL (el archivo de estadísticas es uno por base de datos)

Select count(*) * 164 "size in bytes"
    FROM pg_class
    WHERE relkind ('r','i','S');

Además, debe hacer lo mismo dentro pg_proc, pero en su lugar, el factor será de 28 bytes. Deberá ejecutar esto en cada base de datos y sumarlos todos. Esto es para rastrear estadísticas para el uso de funciones, que se pueden deshabilitar desde el postgresql.conf archivo con la track_functions variable. Además, todos los aspectos de las estadísticas de tiempo de ejecución se pueden encontrar aqui!.

Estadísticas Globales

Estructura de las estadísticas globales:

Structure/Constant Size
PgStat_StatDBEntry 180 bytes
PgStat_GlobalStats 92 bytes
PgStat_ArchiverStats 114 bytes
describers Char (‘D’)

El archivo de estadíticas globales es más pequeño y contiene solo las estadísticas globales y los contadores de las bases de datos. Debería ser algo parecido a:

PGSTAT_FILE_FORMAT_ID + descriptor + PgStat_GlobalStats + PgStat_ArchiverStats + (PgStat_StatDBEntry + descriptor) * numDatabases.

Entonces, como puede ver, la limitación impuesta por AWS en cuanto a está muy por encima de la cantidad de datos almacenados en este directorio en la mayoría de las bases de datos que pueden ejecutarse dento de las expectativas de RDS.

¿Por qué afecta el RDS?

Antes de que se agregara esta característica, “stat_temp_drectory” tenía un lugar en la capa de almacenamiento persistente. Esto era lo mismo que cualquier otra instalación de Postgres de forma predeterminada, sin embargo, debido a las características de almacenamiento de RDS, el impacto podría considerarse mayor que una configuración independiente.

Si su aplicación tiene mucha escritura, verá el impacto en la latencia y las operaciones de escritura.

Una mirada mas profunda

Así la pregunta no tardó en aparecer en la red y yo no fui la excepción ¿Hay alguna forma de calcular previamente el contenido del directorio?

No pude terminar con un número exacto, sin embargo, es posible que sepa que el tamaño de los archivos está más relacionado con la cantidad de tablas, índices, funciones y bases de datos. La siguiente estructura es el núcleo de esta implementación. Es tan importante que realmente tenga una definición “PGSTAT_FILE_FORMAT_ID” que también esté escrita en los archivos de estadísticas.

Todas las estructuras para el contenido de estos archivos se colocan en el “include/pgstat.h” encabezado y su implementación se realiza en “postmaster/pgstat.c” (ya que es un trabajador de inicio). Cada campo que se usa para el uso de contadores “int64” y hyay algunos “timestampz” (64 bits también) con Oid como excepción, que está representado por 32 bits (unsigned int).

Los backends se comunican con el recopilador a través de una “StatMsgType” estructura, cuando es diferente de una estructura con cero “PgStat_TableCounts”. Las estructuras se mantienen en la memoria local de fondo mientras se acumulan recuentos. Entonces, eso significa que no todas las tablas, índices y funciones tendrán una entrada.

¿Qué backends pueden solicitar la escritura de un archivo? Todos los backends, el archivador, el bgwriter. Todos utilizan la misma estructura para pasar los cambios (PgStat_Msg).

Hay 2 funciones para escribir ( pgstat_write_db_statsfile , pgstat_write_statsfiles ) y 2 para leer ( pgstat_read_db_statsfile , pgstat_read_statsfiles ) cada una de las que controlan el db_.stat y global.stat

Referencias

PgStat_StatDBEntry

La estructura de HTAB es opaca y contiene un mapa hash de tablas y funciones que se recopilarán. No nos importa el tamaño de estos mapas, ya que de todos modos no se escribirán en el archivo de estadísticas. Toda la entrada de la base de datos son 22 * 64 bit valores + 1 * 32 bits, por base de datos (180 bytes).

#define PGSTAT_FILE_FORMAT_ID 0x01A5BC9D typedef struct PgStat_StatDBEntry { /* NOTE: The oid type is currently implemented as an unsigned four-byte integer. typedef unsigned int Oid; */ Oid databaseid; PgStat_Counter n_xact_commit; PgStat_Counter n_xact_rollback; PgStat_Counter n_blocks_fetched; PgStat_Counter n_blocks_hit; PgStat_Counter n_tuples_returned; PgStat_Counter n_tuples_fetched; PgStat_Counter n_tuples_inserted; PgStat_Counter n_tuples_updated; PgStat_Counter n_tuples_deleted; TimestampTz last_autovac_time; PgStat_Counter n_conflict_tablespace; PgStat_Counter n_conflict_lock; PgStat_Counter n_conflict_snapshot; PgStat_Counter n_conflict_bufferpin; PgStat_Counter n_conflict_startup_deadlock; PgStat_Counter n_temp_files; PgStat_Counter n_temp_bytes; PgStat_Counter n_deadlocks; PgStat_Counter n_block_read_time; /* times in microseconds */ PgStat_Counter n_block_write_time;

        TimestampTz stat_reset_timestamp;
        TimestampTz stats_timestamp;    /* time of db stats file update */

        /*
        * tables and functions must be last in the struct, because we don't write
        * the pointers out to the stats file.
        */
    HTAB       *tables;             // defined in utils/hsearch.h
    HTAB       *functions;

} PgStat_StatDBEntry;

Estructuras

En general, este es el tamaño de estructura de cada uno:

Structure Detail Total
PgStat_StatTabEntry 20 * 64 bits and 1 * 32 Oid (164 bytes)
PgStat_StatFuncEntry 3 * 64 bits and 1 * 32 Oid (28 bytes)
PgStat_GlobalStats 11 * 64 bits, 8 bytes + 1 * 32 bit, 4 bytes (92 bytes)
PgStat_ArchiverStats 4 * 8 bytes, 2 char 41 bytes (114 bytes)

Espero que hayas disfrutado del artículo!