2010-08-28 20 views
5

Esiste un modo semplice (es. Non hacky) e privo di condizioni di competizione per creare una sequenza partizionata in PostgreSQL. Esempio:Come creare una sequenza partizionata di PostgreSQL?

Utilizzando una sequenza normale Problema:

| Project_ID | Issue | 
| 1   | 1  | 
| 1   | 2  | 
| 2   | 3  | 
| 2   | 4  | 

Utilizzando una sequenza partizionato in Problema:

| Project_ID | Issue | 
| 1   | 1  | 
| 1   | 2  | 
| 2   | 1  | 
| 2   | 2  | 
+0

Sarei felice di sapere se esiste una soluzione elegante a questo problema. La soluzione qui: http://stackoverflow.com/questions/4672629/postgresql-company-id-based-sequence non è male, ma sarà sicura per le transazioni? – Atorian

risposta

1

Non credo ci sia un modo semplice che è facile come sequenze regolari , perché:

  1. Una sequenza memorizza solo un flusso di numeri (valore successivo, ecc.). Ne vuoi uno per ogni partizione.
  2. Le sequenze hanno una gestione speciale che ignora la transazione corrente (per evitare la condizione di competizione). È difficile replicarlo a livello SQL o PL/pgSQL senza usare trucchi come dblink.
  3. La proprietà della colonna DEFAULT può utilizzare un'espressione semplice o una chiamata di funzione come nextval('myseq'); ma non può fare riferimento ad altre colonne per indicare la funzione da cui il flusso dovrebbe provenire.

È possibile creare qualcosa che funzioni, ma probabilmente non lo si riterrà semplice. Affrontare a turno i suddetti problemi:

  1. Utilizzare una tabella per memorizzare il valore successivo per tutte le partizioni, con uno schema come multiseq (partition_id, next_val).
  2. Scrivete una funzione multinextval(seq_table, partition_id) che fa qualcosa di simile al seguente:

    1. Creare una nuova transazione indipendente sulla transazione corrente (un modo per farlo è attraverso dblink; credo anche altri linguaggi server possono farlo più facilmente).
    2. Bloccare la tabella indicata in seq_table.
    3. Aggiorna la riga in cui l'ID della partizione è partition_id, con un valore incrementato. (O inserire una nuova riga con valore 2 se non ce n'è uno esistente.)
    4. Confermare quella transazione e restituire l'ID memorizzato precedente (o 1).
  3. Creare un trigger di inserimento sul tavolo progetti che utilizza una chiamata a multinextval('projects_table', NEW.Project_ID) per inserimenti.

Non ho usato questo intero piano da solo, ma ho provato qualcosa di simile a ogni singolo passaggio. Esempi della funzione multinextval e del trigger possono essere forniti se si desidera provare questo ...

Problemi correlati