Tato otázka vytváří zavádějící předpoklad, že primární klíč vůbec ukládá pořadí tabulky. To ne. Tabulky PostgreSQL nemají definované pořadí, s primárním klíčem nebo bez něj; jsou to "hromady" řádků uspořádaných do bloků stránek. Objednávání se provádí pomocí ORDER BY
klauzule dotazů, pokud je to žádoucí.
Možná si myslíte, že tabulky PostgreSQL jsou uloženy jako indexově orientované tabulky, které jsou uloženy na disku v pořadí primárních klíčů, ale tak Pg nefunguje. Myslím, že InnoDB ukládá tabulky organizované podle primárního klíče (ale nezkontrolováno) a je to volitelné v databázích některých jiných dodavatelů pomocí funkce, která se často nazývá „shlukované indexy“ nebo „indexově organizované tabulky“. Tato funkce není aktuálně podporována PostgreSQL (alespoň od 9.3).
Tedy PRIMARY KEY
je implementován pomocí UNIQUE
index a k tomuto indexu existuje řazení. Je řazen vzestupně od levého sloupce indexu (a tedy primárního klíče) dále, jako by to bylo ORDER BY col1 ASC, col2 ASC, col3 ASC;
. Totéž platí pro jakýkoli jiný index b-stromu (na rozdíl od GiST nebo GIN) indexu v PostgreSQL, protože jsou implementovány pomocí b+stromů.
Takže v tabulce:
CREATE TABLE demo (
a integer,
b text,
PRIMARY KEY(a,b)
);
systém automaticky vytvoří ekvivalent:
CREATE UNIQUE INDEX demo_pkey ON demo(a ASC, b ASC);
To se vám oznámí, když vytvoříte tabulku, např.:
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
Tento index můžete vidět při zkoumání tabulky:
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)
Můžete CLUSTER
na tomto indexu přeuspořádat tabulku podle primárního klíče, ale je to jednorázová operace. Systém toto uspořádání nezachová – i když pokud je na stránkách volné místo kvůli nevýchozímu FILLFACTOR
Myslím, že se o to pokusí.
Jedním z důsledků přirozeného uspořádání indexu (ale ne haldy) je, že je hodně rychlejší vyhledávání:
SELECT * FROM demo ORDER BY a, b;
SELECT * FROM demo ORDER BY a;
než:
SELECT * FROM demo ORDER BY a DESC, b;
a žádný z nich nemůže vůbec používat index primárního klíče, provedou seqscan, pokud nemáte index na b
:
SELECT * FROM demo ORDER BY b, a;
SELECT * FROM demo ORDER BY b;
Je to proto, že PostgreSQL může používat index na (a,b)
téměř stejně rychle jako index na (a)
sám. Nemůže používat index na (a,b)
jako by to byl index na (b)
sám – ani pomalu, to prostě nejde.
Pokud jde o DESC
záznam, proto musí jeden Pg provést zpětný indexový sken, který je pomalejší než běžný dopředný indexový sken. Pokud v EXPLAIN ANALYZE
zaznamenáváte mnoho prohledávání zpětného indexu a můžete si dovolit náklady na výkon dalšího indexu, můžete vytvořit index v poli v DESC
objednávka.
To platí pro WHERE
klauzule, nejen ORDER BY
. Můžete použít index na (a,b)
pro vyhledání WHERE a = 4
nebo WHERE a = 4 AND b = 3
ale ne pro vyhledání WHERE b = 3
sám.