Diese Frage macht die fehlgeleitete Annahme, dass der Primärschlüssel überhaupt eine Tabellenreihenfolge auferlegt. Das tut es nicht. PostgreSQL-Tabellen haben keine definierte Reihenfolge, mit oder ohne Primärschlüssel; Sie sind ein "Haufen" von Zeilen, die in Seitenblöcken angeordnet sind. Die Bestellung wird mit dem ORDER BY
auferlegt Klausel von Abfragen, wenn gewünscht.
Sie denken vielleicht, dass PostgreSQL-Tabellen als indexorientierte Tabellen gespeichert werden, die in der Reihenfolge der Primärschlüssel auf der Festplatte gespeichert werden, aber so funktioniert Pg nicht. Ich denke, InnoDB speichert Tabellen, die nach dem Primärschlüssel organisiert sind (aber nicht überprüft), und es ist optional in den Datenbanken einiger anderer Anbieter, die eine Funktion verwenden, die oft als "Clustered-Indizes" oder "Index-organisierte Tabellen" bezeichnet wird. Diese Funktion wird derzeit nicht von PostgreSQL unterstützt (mindestens ab Version 9.3).
Das heißt, der PRIMARY KEY
wird mit einem UNIQUE
implementiert Index, und es gibt eine Reihenfolge für diesen Index. Es wird in aufsteigender Reihenfolge von der linken Spalte des Indexes (und damit dem Primärschlüssel) an sortiert, als wäre es ORDER BY col1 ASC, col2 ASC, col3 ASC;
. Das gleiche gilt für jeden anderen b-Tree-Index (im Unterschied zu GiST oder GIN) in PostgreSQL, da sie mit b+trees implementiert werden.
Also in der Tabelle:
CREATE TABLE demo (
a integer,
b text,
PRIMARY KEY(a,b)
);
das System erstellt automatisch das Äquivalent von:
CREATE UNIQUE INDEX demo_pkey ON demo(a ASC, b ASC);
Dies wird Ihnen mitgeteilt, wenn Sie eine Tabelle erstellen, zB:
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
Sie können diesen Index sehen, wenn Sie die Tabelle untersuchen:
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)
Sie können CLUSTER
auf diesem Index, um die Tabelle gemäß dem Primärschlüssel neu zu ordnen, aber es ist ein einmaliger Vorgang. Das System behält diese Reihenfolge nicht bei, wenn auf den Seiten aufgrund eines nicht standardmäßigen FILLFACTOR
Platz frei ist Ich denke, es wird versuchen.
Eine Folge der inhärenten Reihenfolge des Index (aber nicht des Haufens) ist, dass es viel ist schneller zu suchen nach:
SELECT * FROM demo ORDER BY a, b;
SELECT * FROM demo ORDER BY a;
als:
SELECT * FROM demo ORDER BY a DESC, b;
und keiner von beiden kann den Primärschlüsselindex überhaupt verwenden, sie führen einen Seqscan durch, es sei denn, Sie haben einen Index auf b
:
SELECT * FROM demo ORDER BY b, a;
SELECT * FROM demo ORDER BY b;
Dies liegt daran, dass PostgreSQL einen Index für (a,b)
verwenden kann fast so schnell wie ein Index auf (a)
allein. Es kann keinen Index auf (a,b)
verwenden als wäre es ein Index auf (b)
allein - nicht einmal langsam, es kann einfach nicht.
Wie für DESC
Eintrag, für diesen einen Pg muss ein Rückwärts-Index-Scan durchgeführt werden, der langsamer ist als ein gewöhnlicher Vorwärts-Index-Scan. Wenn Sie viele Reverse-Index-Scans in EXPLAIN ANALYZE
sehen und Sie sich die Leistungskosten des zusätzlichen Index leisten können, können Sie einen Index für das Feld in DESC
erstellen bestellen.
Dies gilt für WHERE
Klauseln, nicht nur ORDER BY
. Sie können einen Index für (a,b)
verwenden um nach WHERE a = 4
zu suchen oder WHERE a = 4 AND b = 3
aber nicht um nach WHERE b = 3
zu suchen allein.