Estoy configurando una nueva base de datos de PostgreSQL 9 que contendrá millones (o tal vez miles de millones) de filas. Así que decidí dividir los datos usando la herencia de PostgreSQL.Elección de la regla de partición correcta
he creado una tabla maestra como esta (simplificado por ejemplo):
CREATE TABLE mytable
(
user_id integer,
year integer,
CONSTRAINT pk_mytable PRIMARY KEY (user_id, year)
);
Y 10 de partición tablas:
CREATE TABLE mytable_0() INHERITS (mytable);
CREATE TABLE mytable_1() INHERITS (mytable);
...
CREATE TABLE mytable_9() INHERITS (mytable);
Sé que las filas se accederá siempre desde la aplicación usando un único condición de usuario_id. Así que me gustaría extender los datos "bastante" por igual sobre las 10 tablas usando una regla basada en user_id.
Para ajustar consultas sobre la tabla maestra, mi primera idea era utilizar una restricción de comprobación módulo:
ALTER TABLE mytable_0 ADD CONSTRAINT mytable_user_id_check CHECK (user_id % 10 = 0);
ALTER TABLE mytable_1 ADD CONSTRAINT mytable_user_id_check CHECK (user_id % 10 = 1);
...
El problema es, cuando me consultan la tabla maestra "mitabla" con la condición de user_id, PostgreSQL analizador de comprobar todas las tablas y no se benefician de la restricción de comprobación:
EXPLAIN SELECT * FROM mytable WHERE user_id = 12345;
"Result (cost=0.00..152.69 rows=64 width=36)"
" -> Append (cost=0.00..152.69 rows=64 width=36)"
" -> Seq Scan on mytable (cost=0.00..25.38 rows=6 width=36)"
" Filter: (user_id = 12345)"
" -> Seq Scan on mytable_0 mytable (cost=0.00..1.29 rows=1 width=36)"
" Filter: (user_id = 12345)"
" -> Seq Scan on mytable_1 mytable (cost=0.00..1.52 rows=1 width=36)"
" Filter: (user_id = 12345)"
...
" -> Seq Scan on mytable_9 mytable (cost=0.00..1.52 rows=1 width=36)"
" Filter: (user_id = 12345)"
Mientras que si utilizo una restricción cHECK clásico como este (y el reparto que coincide con la regla):
ALTER TABLE mytable_0 ADD CONSTRAINT mytable_user_id_check CHECK (user_id BETWEEN 1 AND 10000);
ALTER TABLE mytable_1 ADD CONSTRAINT mytable_user_id_check CHECK (user_id BETWEEN 10001 AND 20000);
...
va a escanear sólo las tablas que coinciden con la condición (mitabla y mytable_1 en este ejemplo):
"Result (cost=0.00..152.69 rows=64 width=36)"
" -> Append (cost=0.00..152.69 rows=64 width=36)"
" -> Seq Scan on mytable (cost=0.00..25.38 rows=6 width=36)"
" Filter: (user_id = 12345)"
" -> Seq Scan on mytable_1 mytable (cost=0.00..1.52 rows=1 width=36)"
" Filter: (user_id = 12345)"
Pero el uso de tales restricción de comprobación es difícil de mantener debido a que el número de usuarios que se rellenará en el las tablas cambiarán a lo largo de los años. miles primero, quizás millones o más en el futuro cercano ...
¿Qué regla podría usar para dividir equitativamente mis datos en las 10 tablas que podrían beneficiarse de una restricción de verificación para que un SELECT en la tabla maestra escanee únicamente la mesa correcta ...?
Gracias, Nico