El Modelo de Particionamiento
El particionamiento divide una tabla lógica en muchas piezas físicas, mientras permite que el código de la aplicación siga consultándola como si fuera una sola tabla.
Busca en todas las páginas de la documentación
El particionamiento divide una tabla lógica en muchas piezas físicas, mientras permite que el código de la aplicación siga consultándola como si fuera una sola tabla.
Esa división suena como un detalle de almacenamiento, pero la clave de partición que eliges se convierte en una promesa estructural sobre cómo se comportarán todas las futuras consultas, índices y trabajos de mantenimiento.
Esta página construye el modelo mental detrás del particionamiento declarativo de PostgreSQL, para que las páginas más mecánicas de esta sección (sintaxis DDL, poda, retención) tengan sentido como consecuencias de ese modelo en lugar de recetas aisladas.
Una tabla particionada en PostgreSQL se declara una vez, con PARTITION BY RANGE, LIST o HASH sobre una clave de partición seleccionada.
Cada partición hija es una tabla física real que contiene una porción definida de filas, y la tabla padre en sí misma no almacena ninguna fila.
CREATE TABLE events (
event_id bigint GENERATED ALWAYS AS IDENTITY,
occurred_at timestamptz NOT NULL,
PRIMARY KEY (event_id, occurred_at)
) PARTITION BY RANGE (occurred_at);El particionamiento por rango asigna filas a una partición basándose en dónde cae un valor entre límites, y es el ajuste natural para datos de series temporales como eventos o logs.
El particionamiento por lista asigna filas por pertenencia a un valor exacto, lo cual se ajusta a columnas de baja cardinalidad como región o nivel de inquilino.
El particionamiento por hash distribuye las filas de manera uniforme a través de un número fijo de particiones usando un hash de la clave, para casos donde no existe un agrupamiento natural por rango o lista, pero la distribución uniforme sigue siendo importante.
La elección entre estos tres es realmente una elección sobre en qué se filtrarán las futuras consultas, porque eso es lo que determina si PostgreSQL puede omitir particiones por completo.
La capacidad del planificador para omitir particiones irrelevantes se llama poda de particiones (partition pruning), y es el argumento de rendimiento completo para el particionamiento.
Cuando la cláusula WHERE de una consulta restringe la clave de partición a un rango o a un conjunto de valores, el planificador puede determinar en tiempo de planificación (o en algunos casos en tiempo de ejecución) qué particiones hijas podrían contener filas coincidentes, y escanear solo esas.
EXPLAIN (COSTS OFF)
SELECT * FROM events WHERE occurred_at >= '2026-01-01' AND occurred_at < '2026-02-01';
-- Un plan podado toca solo la partición events_2026_01Si una consulta no filtra en la clave de partición en absoluto, la poda no puede ocurrir y la consulta escanea todas las particiones, lo que puede ser más lento que la consulta equivalente contra una tabla no particionada debido a la sobrecarga adicional de planificación.
Es por esto que la clave de partición no es un detalle de implementación de almacenamiento para elegir al final, es una predicción sobre la forma dominante de la cláusula WHERE en la carga de trabajo de consulta real de la tabla.
Los índices en una tabla particionada se declaran una vez en el padre y PostgreSQL propaga la definición a cada partición hija existente y futura, pero cada hija aún almacena y mantiene su propio índice físico.
Eso significa que agregar un índice a una tabla particionada con muchas particiones es realmente agregar muchos índices a la vez, y debe planificarse con el mismo cuidado que cualquier otra operación DDL de tabla grande.
Una partición por defecto existe para capturar filas que no coinciden con ningún límite de partición explícito, lo que evita fallos de inserción durante el despliegue, pero tiene un costo: las filas en la partición por defecto no pueden ser podadas de ninguna consulta, porque el planificador no puede descartarla para ningún predicado.
El caso de mantenimiento del particionamiento es a menudo el argumento más fuerte en la práctica, incluso por delante de la velocidad de consulta.
Eliminar un mes de datos históricos de una tabla no particionada de mil millones de filas significa un DELETE lento y con mucho registro de transacciones que debe ser vaciado (vacuumed) después; desvincular (detach) una partición es una operación de metadatos rápida que elimina los datos instantáneamente.
ALTER TABLE events DETACH PARTITION events_2025_01;Vacuum y autovacuum también se benefician del particionamiento indirectamente, porque cada partición es una tabla separada para los propósitos de autovacuum, por lo que una partición reciente y activa (hot) que se actualiza frecuentemente puede ser vaciada sin tocar particiones históricas frías que no han cambiado.
La elección entre particionamiento por rango, lista y hash a escala real generalmente se reduce a cuál coincide con la forma de filtro real en producción, no cuál es teóricamente más elegante para los datos.
| Enfoque | Fortaleza | Debilidad | Mejor Ajuste |
|---|---|---|---|
| Particionamiento por rango | Ajuste natural para datos de series temporales; soporta retención fácil vía detach | Requiere creación continua de particiones a medida que avanza el tiempo | Tablas de eventos, logs y series temporales |
| Particionamiento por lista | Mapeo directo a un conjunto de valores conocido y pequeño | Los nuevos valores necesitan nuevas particiones o una captura por defecto | Región, nivel de inquilino u otras columnas de baja cardinalidad |
| Particionamiento por hash | Distribución uniforme de escritura sin clave de rango o lista natural | Sin beneficio de poda a menos que las consultas filtren en la clave hash con igualdad | Tablas de alta escritura que necesitan distribución, no acceso basado en tiempo o categoría |
| Sin particionamiento | Más simple de operar; no se necesita planificación de poda | El costo de borrado masivo y vacuum escala con el tamaño total de la tabla | Tablas que permanecen pequeñas o cuyos borrados son raros |
El particionamiento también interactúa con las reglas de clave primaria y restricciones únicas en PostgreSQL: cualquier restricción única, incluida la clave primaria, debe incluir la clave de partición como parte de sus columnas, porque la unicidad solo se puede aplicar dentro de cada partición física, no en todas ellas a la vez.
Esa restricción da forma al diseño de la clave antes de lo que la mayoría de los equipos esperan, y vale la pena resolverla durante la etapa de modelado lógico en lugar de descubrirla al escribir la primera sentencia CREATE TABLE PARTITION BY.
WHERE tiende a producir una tabla que no puede podar las consultas que realmente se ejecutan contra ella.ALTER ligera.Es una tabla lógica declarada con PARTITION BY, respaldada por múltiples tablas hijas físicas que cada una contiene una porción definida de filas.
La tabla padre en sí misma no almacena filas.
La poda de particiones es la capacidad del planificador para omitir tablas hijas que no pueden contener filas coincidentes, basándose en la cláusula WHERE de la consulta.
Es el principal beneficio de rendimiento del particionamiento, y solo se activa cuando una consulta filtra en la clave de partición.
El planificador no puede descartar ninguna partición, por lo que las escanea todas, lo que puede ser más lento que consultar una tabla no particionada equivalente debido a la sobrecarga adicional de planificación por partición.
Las restricciones de unicidad, incluida la clave primaria, solo se pueden aplicar dentro de una única partición física, no en todas las particiones a la vez.
Incluir la clave de partición en la restricción es cómo PostgreSQL garantiza que la unicidad global se cumpla realmente.
Sí, cuando los datos antiguos se alinean con particiones completas: desvincular o eliminar una partición es una operación de metadatos rápida, en comparación con un DELETE fila por fila que luego necesita ser vaciado en una tabla no particionada.
No, un índice declarado en la tabla padre se propaga automáticamente a cada partición hija existente y futura.
Cada hija aún almacena su propia copia física de ese índice.
Una partición por defecto captura filas que no coinciden con los límites de ninguna partición explícita, evitando fallos de inserción durante el despliegue o valores inesperados.
Debe ser monitoreada y mantenerse pequeña, porque las filas dentro de ella nunca pueden ser podadas.
Indirectamente, sí: cada partición es una tabla separada para los propósitos de autovacuum, por lo que una partición reciente y activa puede ser vaciada frecuentemente mientras que las particiones históricas frías se dejan sin tocar.
No como una operación ligera: la clave de partición afecta a cada restricción única en la tabla, por lo que cambiarla típicamente requiere reconstruir la tabla bajo un nuevo esquema de particionamiento.
Es por esto que la clave merece un análisis real antes de crear la primera partición.
Ambas, pero el caso de mantenimiento (retención rápida vía detach, vacuum aislado por partición) es a menudo la ganancia más fuerte y confiable en producción, por delante de la velocidad de consulta bruta.
La velocidad de consulta depende completamente de si la poda se aplica realmente.
No hay un número universal, pero la sobrecarga de planificación crece con el número de particiones, y un número de particiones ilimitado y en constante crecimiento (una por día para siempre, sin retención) eventualmente tensa el tiempo de planificación incluso cuando la poda funciona correctamente.
Las políticas de retención existen en parte para mantener esto acotado.
Versiones de Stack: Esta página fue escrita para PostgreSQL 18.4 (estable 18, mantenimiento 17).
Revisado por Chris St. John·Última actualización: 15 jul 2026