Denna fråga gör det missriktade antagandet att primärnyckeln överhuvudtaget inför en tabellordning. Det gör det inte. PostgreSQL-tabeller har ingen definierad ordning, med eller utan en primärnyckel; de är en "hög" av rader ordnade i sidblock. Beställning åläggs med ORDER BY
klausul av frågor när så önskas.
Du kanske tänker att PostgreSQL-tabeller lagras som indexorienterade tabeller som lagras på disken i primärnyckelordning, men det är inte så Pg fungerar. Jag tror att InnoDB lagrar tabeller organiserade efter primärnyckeln (men har inte markerat), och det är valfritt i vissa andra leverantörers databaser med en funktion som ofta kallas "klustrade index" eller "indexorganiserade tabeller". Den här funktionen stöds för närvarande inte av PostgreSQL (åtminstone från 9.3).
Som sagt, den PRIMARY KEY
implementeras med en UNIQUE
index, och det finns en ordning på det indexet. Den sorteras i stigande ordning från den vänstra kolumnen i indexet (och därmed primärnyckeln) och framåt, som om det vore ORDER BY col1 ASC, col2 ASC, col3 ASC;
. Detsamma gäller för alla andra b-träd (till skillnad från GiST eller GIN) index i PostgreSQL, eftersom de är implementerade med b+träd.
Så i tabellen:
CREATE TABLE demo (
a integer,
b text,
PRIMARY KEY(a,b)
);
systemet kommer automatiskt att skapa motsvarigheten till:
CREATE UNIQUE INDEX demo_pkey ON demo(a ASC, b ASC);
Detta rapporteras till dig när du skapar en tabell, t.ex.:
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 detta index när du granskar 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å detta index för att ordna om tabellen enligt primärnyckeln, men det är en engångsoperation. Systemet upprätthåller inte den ordningen – dock om det finns ledigt utrymme på sidorna på grund av en FILLFACTOR
som inte är standard Jag tror att det kommer att försöka.
En konsekvens av indexets inneboende ordning (men inte högen) är att det är mycket snabbare att söka efter:
SELECT * FROM demo ORDER BY a, b;
SELECT * FROM demo ORDER BY a;
än:
SELECT * FROM demo ORDER BY a DESC, b;
och ingen av dessa kan använda primärnyckelindexet alls, de kommer att göra en seqscan om du inte har ett index på b
:
SELECT * FROM demo ORDER BY b, a;
SELECT * FROM demo ORDER BY b;
Detta beror på att PostgreSQL kan använda ett index på (a,b)
nästan lika snabbt som ett index på (a)
ensam. Den kan inte använda ett index på (a,b)
som om det vore ett index på (b)
ensam - inte ens långsamt, det går bara inte.
När det gäller DESC
för att en Pg måste göra en omvänd indexskanning, som är långsammare än en vanlig framåtindexavsökning. Om du ser många omvända indexsökningar i EXPLAIN ANALYZE
och du har råd med prestandakostnaden för det extra indexet, du kan skapa ett index på fältet i DESC
beställa.
Detta gäller för WHERE
satser, inte bara ORDER BY
. Du kan använda ett index på (a,b)
för att söka efter WHERE a = 4
eller WHERE a = 4 AND b = 3
men inte för att söka efter WHERE b = 3
ensam.