2012-04-21 30 views
13

Tenemos un portal de comercio electrónico con una base de datos Postgresql 9.1. Una tabla muy importante tiene en este momento 32 millones de registros. Si queremos entregar todos los artículos, esta tabla crecerá a 320 millones de registros, en su mayoría fechas. Que sería demasiado pesado.¿Cuáles serían los pasos correctos para la partición horizontal en Postgresql?

Así que estamos pensando en la partición/fragmentación horizontal. Podemos dividir los elementos en esta tabla en 12 piezas horizontales (1 por mes). ¿Cuáles serían los mejores pasos y técnicas para hacerlo? ¿La partición horizontal dentro de la base de datos sería lo suficientemente buena o tendremos que empezar a pensar en la fragmentación?

Respuesta

24

Mientras que 320 millones no es pequeño, tampoco es muy grande.

En gran medida depende de las consultas que ejecuta en la tabla. Si siempre incluye la clave de partición en sus consultas, entonces la partición "normal" probablemente funcione.

Un ejemplo de esto se puede encontrar en el PostgreSQL wiki:
http://wiki.postgresql.org/wiki/Month_based_partitioning

El manual también explica algunas de las advertencias de la partición:
http://www.postgresql.org/docs/current/interactive/ddl-partitioning.html

Si usted está pensando en sharding, es posible que lea cómo Instagram (que es impulsado por PostgreSQL) ha implementado que:

http://instagram-engineering.tumblr.com/post/10853187575/sharding-ids-at-instagram

Si tiene principalmente consultas de lectura, otra opción podría ser utilizar la replicación de transmisión para configurar varios servidores y distribuir las consultas de lectura conectándose al Hot-Standby para el acceso de lectura y conectándose al maestro para el acceso de escritura. Creo que pg-pool II puede hacer eso (algo) automáticamente. Eso se puede combinar con la partición para reducir aún más el tiempo de ejecución de la consulta.

Si le gusta la aventura y no tienen necesidades muy inmediatas para hacerlo, también puede considerar Postgres-XC que promete apoyar la escala horizontal transparente:
http://postgres-xc.sourceforge.net/

No hay versión final todavía, pero parece que esto no está tomando demasiado tiempo

+1

Gracias mucho por su gran comprensión! – Brambo76

+0

+1 ¡Muy informativo! –

+5

Al igual que un punto de datos, nuestra tienda cuenta con más de 300 millones de filas en una de nuestras tablas con mayor acceso, sin particiones ni fragmentación, y funciona bien.Para reafirmar algo de lo anterior, los factores críticos para hacer que el particionamiento valga la pena es tener una clave de partición que a menudo se usa para limitar las filas de interés en las consultas, y que desean eliminar periódicamente una partición completa. (Es mucho más rápido eliminar una partición que eliminar 1/12 de sus filas). – kgrittn

1

Aquí está mi código de ejemplo para la partición: t_master es una vista que seleccionar/insertar/actualizar/borrar en su aplicación t_1 y t_2 es ​​las tablas subyacentes en realidad el almacenamiento datos.

create or replace view t_master(id, col1) 
as 
select id, col1 from t_1 
union all 
select id, col1 from t_2 


CREATE TABLE t_1 
(
    id bigint PRIMARY KEY, 
    col1 text 
); 

CREATE TABLE t_2 
(
    id bigint PRIMARY KEY, 
    col1 text 
); 



CREATE OR REPLACE FUNCTION t_insert_partition_function() 
returns TRIGGER AS $$ 
begin 
raise notice '%s', 'hello'; 
    execute 'insert into t_' 
     || (mod(NEW.id, 2)+ 1) 
     || ' values ($1, $2)' USING NEW.id, NEW.col1 ; 
    RETURN NULL; 
end; 
$$ 
LANGUAGE plpgsql; 

CREATE OR REPLACE FUNCTION t_update_partition_function() 
returns TRIGGER AS $$ 
begin 
    raise notice '%s', 'hello'; 
    execute 'update t_' 
     || (mod(NEW.id, 2)+ 1) 
     || ' set id = $1, col1 = $2 where id = $1' 
     USING NEW.id, NEW.col1 ; 
    RETURN NULL; 
end; 
$$ 
LANGUAGE plpgsql; 

CREATE OR REPLACE FUNCTION t_delete_partition_function() 
returns TRIGGER AS $$ 
begin 
    raise notice '%s', 'hello'; 
    execute 'delete from t_' 
     || (mod(OLD.id, 2)+ 1) 
     || ' where id = $1' 
     USING OLD.id; 
    RETURN NULL; 
end; 
$$ 
LANGUAGE plpgsql; 



CREATE TRIGGER t_insert_partition_trigger instead of INSERT 
ON t_master FOR each row 
execute procedure t_insert_partition_function(); 

CREATE TRIGGER t_update_partition_trigger instead of update 
ON t_master FOR each row 
execute procedure t_update_partition_function(); 

CREATE TRIGGER t_delete_partition_trigger instead of delete 
ON t_master FOR each row 
execute procedure t_delete_partition_function(); 
1

Si no te importa la actualización a PostgreSQL 9.4, entonces se podría utilizar el pg_shard extension, que le permite de forma transparente Fragmento de una tabla de PostgreSQL a través de muchas máquinas. Cada fragmento se almacena como una tabla PostgreSQL regular en otro servidor PostgreSQL y se replica en otros servidores. Utiliza la partición hash para decidir qué fragmento (s) usar para una consulta determinada. pg_shard funcionaría bien si sus consultas tienen una dimensión de partición natural (por ejemplo, ID de cliente).

Más información: https://github.com/citusdata/pg_shard

Cuestiones relacionadas