2012-04-21 6 views
13

Abbiamo un portale di e-commerce con un database Postgresql 9.1. Un tavolo molto importante ha al momento 32 milioni di dischi. Se vogliamo consegnare tutti gli articoli, questa tabella crescerà fino a 320 milioni di record, per lo più date. Quale sarebbe pesante.Quali sarebbero i passi giusti per il partizionamento orizzontale in Postgresql?

Quindi stiamo pensando al partizionamento orizzontale/sharding. Possiamo dividere gli elementi in questa tabella in 12 pezzi orizzontali (1 al mese). Quali sarebbero i migliori passi e le migliori tecniche per farlo? Il partizionamento orizzontale all'interno del database sarebbe abbastanza buono o dovremmo cominciare a pensare al sharding?

risposta

24

Anche se 320 milioni non sono piccoli, non è neanche troppo grande.

Dipende in gran parte dalle query eseguite sul tavolo. Se includi sempre la chiave di partizione nelle tue query, il partizionamento "normale" probabilmente funzionerebbe.

Un esempio di questo può essere trovata nel wiki PostgreSQL:
http://wiki.postgresql.org/wiki/Month_based_partitioning

Il manuale spiega anche alcune delle avvertenze di partizionamento:
http://www.postgresql.org/docs/current/interactive/ddl-partitioning.html

Se stai pensando di sharding, si potrebbe leggi come Instagram (implementato da PostgreSQL) ha implementato:

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

Se si dispone principalmente di query di lettura, un'altra opzione potrebbe essere quella di utilizzare la replica di streaming per configurare più server e distribuire le query di lettura connettendosi a hot-standby per l'accesso in lettura e la connessione al master per l'accesso in scrittura. Penso che lo pg-pool II possa farlo (in qualche modo) automaticamente. Questo può essere combinato con il partizionamento per ridurre ulteriormente il runtime della query.

se siete avventurosi e non hanno esigenze molto immediati per farlo, si potrebbe anche prendere in considerazione Postgres-XC che promette di supporto trasparente scala orizzontale:
http://postgres-xc.sourceforge.net/

Non ci sono release finale, ma sembra che questo non sta impiegando troppo tempo

+1

ringrazio molto per il vostro grande intuizione! – Brambo76

+0

+1 Molto informativo! –

+5

Proprio come un punto dati, il nostro negozio ha oltre 300 milioni di righe in una delle nostre tabelle più accessibili, senza partizioni o sharding, e funziona perfettamente.Per ridefinire alcuni dei fattori sopra citati, i fattori critici per rendere utile il partizionamento sono la presenza di una chiave di partizione che viene spesso utilizzata per limitare le righe di interesse nelle query e che desiderano rilasciare periodicamente un'intera partizione. (È molto più veloce rilasciare una partizione piuttosto che cancellare 1/12 delle tue righe). – kgrittn

1

Ecco il mio codice di esempio per il partizionamento: t_master è una vista di essere selezionate/inserimento/aggiornamento/cancellazione nell'applicazione t_1 e t_2 è le tabelle sottostanti in realtà la memorizzazione del dati.

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

Se non ti dispiace l'aggiornamento a PostgreSQL 9.4, allora si potrebbe utilizzare la pg_shard extension, che consente di Shard in modo trasparente una tabella di PostgreSQL in molte macchine. Ogni frammento viene memorizzato come una normale tabella PostgreSQL su un altro server PostgreSQL e replicata su altri server. Usa hash-partizionamento per decidere quale shard (s) utilizzare per una determinata query. pg_shard funzionerebbe bene se le tue query hanno una dimensione di partizione naturale (ad esempio, ID cliente).

Maggiori informazioni: https://github.com/citusdata/pg_shard

Problemi correlati