2012-11-02 9 views

risposta

36

Questa domanda fa presupporre erroneamente che la chiave primaria imponga un ordine di tabella. Non è così. Le tabelle PostgreSQL non hanno un ordine definito, con o senza una chiave primaria; sono un "mucchio" di righe disposte in blocchi di pagina. L'ordine viene imposto utilizzando la clausola ORDER BY quando richiesto.

Si potrebbe pensare che le tabelle PostgreSQL siano memorizzate come tabelle orientate agli indici che vengono memorizzate su disco in ordine di chiave primaria, ma non è così che funziona Pg. Penso che InnoDB memorizzi le tabelle organizzate dalla chiave primaria (ma non siano state controllate), ed è facoltativa in alcuni database di altri fornitori utilizzando una funzione spesso chiamata "indici cluster" o "tabelle organizzate per indice". Questa funzione non è attualmente supportata da PostgreSQL (come minimo da 9.3).

Detto questo, lo PRIMARY KEY viene implementato utilizzando un indice UNIQUE e vi è un ordinamento per tale indice. È ordinato in ordine crescente dalla colonna sinistra dell'indice (e quindi dalla chiave primaria) in poi, come se fosse ORDER BY col1 ASC, col2 ASC, col3 ASC;. Lo stesso vale per qualsiasi altro indice b-tree (come distinto da GiST o GIN) in PostgreSQL, dato che sono implementati usando b+trees.

Così nella tabella:

CREATE TABLE demo (
    a integer, 
    b text, 
    PRIMARY KEY(a,b) 
); 

il sistema creerà automaticamente l'equivalente di:

CREATE UNIQUE INDEX demo_pkey ON demo(a ASC, b ASC); 

Questo è riportato a voi quando si crea una tabella, ad esempio:

regress=>  CREATE TABLE demo (
regress(>  a integer, 
regress(>  b text, 
regress(>  PRIMARY KEY(a,b) 
regress(> ); 
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index "demo_pkey" for table "demo" 
CREATE TABLE 

È possibile visualizzare questo indice durante l'esame della tabella:

È possibile effettuare il CLUSTER in questo indice per riordinare la tabella in base alla chiave primaria, ma è un'operazione singola. Il sistema non manterrà questo ordine, anche se c'è spazio libero nelle pagine a causa di un valore non predefinito FILLFACTOR, penso che proverà a farlo.

Una conseguenza della ordinazione intrinseca dell'indice (ma non l'heap) è che è molto più veloce per cercare:

SELECT * FROM demo ORDER BY a, b; 
SELECT * FROM demo ORDER BY a; 

di:

SELECT * FROM demo ORDER BY a DESC, b; 

e nessuno dei due questi possono utilizzare l'indice della chiave primaria, eseguiranno un seqscan a meno che non si disponga di un indice su b:

SELECT * FROM demo ORDER BY b, a; 
SELECT * FROM demo ORDER BY b; 

Questo è perché PostgreSQL può utilizzare un indice su (a,b) quasi come un indice su (a) da solo.Non può usare un indice su (a,b) come se fosse un indice su (b) da solo - nemmeno lentamente, semplicemente non può.

Come per la voce DESC, per quel Pg deve eseguire una scansione dell'indice inverso, che è più lenta di una normale scansione indice in avanti. Se stai vedendo molte scansioni dell'indice inverso in EXPLAIN ANALYZE e puoi permetterti il ​​costo delle prestazioni dell'indice extra, puoi creare un indice sul campo nell'ordine DESC.

Questo vale per le clausole WHERE, non solo per ORDER BY. È possibile utilizzare un indice su (a,b) per cercare WHERE a = 4 o WHERE a = 4 AND b = 3 ma non per cercare solo WHERE b = 3.

+0

Quindi, dovrei presumere che le ricerche sulla base della colonna più a sinistra siano le più veloci rispetto alle colonne a destra (le colonne di cui sto parlando sono tutte colonne che formano la chiave primaria)? –

+1

@AbhishekJain corretto; usando la colonna più a sinistra del PK (o le ricerche che usano entrambe le colonne) userà l'indice, mentre usando la colonna più a destra del solo PK * non sarà possibile usare l'indice. Può essere utile creare un secondo indice solo sulla colonna più a destra se è necessario eseguire molte ricerche su questo o invertire l'ordine della chiave primaria se non è necessario cercare l'altra colonna da sola. –

+2

@AbhishekJain Prego. Vi consiglio vivamente di familiarizzare con il comando 'EXPLAIN ANALYZE' e con la shell di comando' psql'. Entrambi ti aiuteranno a capire come PostgreSQL funzioni molto meglio, analizzare come vengono eseguite le query, testare diverse strategie di indicizzazione, ecc. Http://explain.depesz.com/ può essere utile anche quando cerchi di comprendere piani di query grandi e complessi. –

Problemi correlati