Dette spørgsmål gør den misforståede antagelse, at den primære nøgle overhovedet pålægger en tabelrækkefølge. Det gør den ikke. PostgreSQL-tabeller har ingen defineret rækkefølge, med eller uden en primær nøgle; de er en "dynge" af rækker arrangeret i sideblokke. Bestilling pålægges ved hjælp af ORDER BY
klausul af forespørgsler, når det ønskes.
Du tænker måske, at PostgreSQL-tabeller er gemt som indeksorienterede tabeller, der er gemt på disken i primær nøglerækkefølge, men det er ikke sådan Pg fungerer. Jeg tror, at InnoDB gemmer tabeller organiseret efter den primære nøgle (men har ikke markeret), og det er valgfrit i nogle andre leverandørers databaser ved at bruge en funktion, der ofte kaldes "klyngede indekser" eller "indeksorganiserede tabeller". Denne funktion er i øjeblikket ikke understøttet af PostgreSQL (i det mindste fra 9.3).
Når det er sagt, PRIMARY KEY
er implementeret ved hjælp af en UNIQUE
indeks, og der er en rækkefølge til det indeks. Det er sorteret i stigende rækkefølge fra venstre kolonne i indekset (og derfor den primære nøgle) og frem, som om det var ORDER BY col1 ASC, col2 ASC, col3 ASC;
. Det samme gælder for ethvert andet b-træ (til forskel fra GiST eller GIN) indeks i PostgreSQL, da de er implementeret ved hjælp af b+træer.
Så i tabellen:
CREATE TABLE demo (
a integer,
b text,
PRIMARY KEY(a,b)
);
systemet vil automatisk oprette det, der svarer til:
CREATE UNIQUE INDEX demo_pkey ON demo(a ASC, b ASC);
Dette rapporteres til dig, når du opretter en tabel, f.eks.:
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
Du kan se dette indeks, når du undersøger tabellen:
regress=> \d demo
Table "public.demo"
Column | Type | Modifiers
--------+---------+-----------
a | integer | not null
b | text | not null
Indexes:
"demo_pkey" PRIMARY KEY, btree (a, b)
Du kan CLUSTER
på dette indeks for at omarrangere tabellen i henhold til den primære nøgle, men det er en engangsoperation. Systemet vil ikke opretholde den rækkefølge - dog hvis der er ledig plads på siderne på grund af en ikke-standard FILLFACTOR
Det tror jeg, det vil forsøge.
En konsekvens af den iboende rækkefølge af indekset (men ikke bunken) er, at det er meget hurtigere at søge efter:
SELECT * FROM demo ORDER BY a, b;
SELECT * FROM demo ORDER BY a;
end:
SELECT * FROM demo ORDER BY a DESC, b;
og ingen af disse kan bruge det primære nøgleindeks overhovedet, de laver en seqscan, medmindre du har et indeks på b
:
SELECT * FROM demo ORDER BY b, a;
SELECT * FROM demo ORDER BY b;
Dette skyldes, at PostgreSQL kan bruge et indeks på (a,b)
næsten lige så hurtigt som et indeks på (a)
alene. Den kan ikke bruge et indeks på (a,b)
som om det var et indeks på (b)
alene - ikke engang langsomt, det kan den bare ikke.
Hvad angår DESC
indtastning, for at en Pg skal lave en omvendt indeksscanning, som er langsommere end en almindelig fremadgående indeksscanning. Hvis du ser mange omvendte indeksscanninger i EXPLAIN ANALYZE
og du har råd til ydeevneomkostningerne for det ekstra indeks, du kan oprette et indeks på feltet i DESC
bestille.
Dette gælder for WHERE
klausuler, ikke kun ORDER BY
. Du kan bruge et indeks på (a,b)
for at søge efter WHERE a = 4
eller WHERE a = 4 AND b = 3
men ikke for at søge efter WHERE b = 3
alene.