Този въпрос прави погрешното предположение, че първичният ключ изобщо налага ред на таблицата. Не е така. PostgreSQL таблиците нямат дефиниран ред, със или без първичен ключ; те са "купчина" от редове, подредени в блокове на страници. Подреждането се налага с помощта на ORDER BY
клауза от заявки, когато желаете.
Може би си мислите, че PostgreSQL таблиците се съхраняват като индексно-ориентирани таблици, които се съхраняват на диска в ред на първичен ключ, но Pg не работи така. Мисля, че InnoDB съхранява таблици, организирани от първичния ключ (но не е проверено) и е по избор в бази данни на някои други доставчици, използвайки функция, често наричана "клъстерирани индекси" или "организирани от индекс таблици". Тази функция в момента не се поддържа от PostgreSQL (поне от 9.3).
Това каза, PRIMARY KEY
се реализира с помощта на UNIQUE
индекс и има подреждане на този индекс. Той се сортира във възходящ ред от лявата колона на индекса (и следователно първичния ключ) нататък, сякаш е ORDER BY col1 ASC, col2 ASC, col3 ASC;
. Същото важи и за всяко друго b-дърво (за разлика от GiST или GIN) индекс в PostgreSQL, тъй като те са имплементирани с помощта на b+дървета.
Така че в таблицата:
CREATE TABLE demo (
a integer,
b text,
PRIMARY KEY(a,b)
);
системата автоматично ще създаде еквивалента на:
CREATE UNIQUE INDEX demo_pkey ON demo(a ASC, b ASC);
Това ви се съобщава, когато създавате таблица, напр.:
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
Можете да видите този индекс, когато разглеждате таблицата:
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)
Можете да CLUSTER
на този индекс, за да пренаредите таблицата според първичния ключ, но това е еднократна операция. Системата няма да поддържа това подреждане - въпреки че ако има свободно място на страниците поради непонятно FILLFACTOR
Мисля, че ще се опита.
Едно следствие от присъщото подреждане на индекса (но не и на купчината) е, че той е много по-бързо за търсене на:
SELECT * FROM demo ORDER BY a, b;
SELECT * FROM demo ORDER BY a;
отколкото:
SELECT * FROM demo ORDER BY a DESC, b;
и нито един от тях изобщо не може да използва индекса на първичния ключ, те ще направят seqscan, освен ако нямате индекс на b
:
SELECT * FROM demo ORDER BY b, a;
SELECT * FROM demo ORDER BY b;
Това е така, защото PostgreSQL може да използва индекс на (a,b)
почти толкова бързо, колкото индекс на (a)
сам. Не може да използва индекс на (a,b)
сякаш е индекс на (b)
сам - дори не бавно, просто не може.
Що се отнася до DESC
запис, за този Pg трябва да извърши обратно индексно сканиране, което е по-бавно от обикновеното сканиране на индекса напред. Ако виждате много обратни индексни сканирания в EXPLAIN ANALYZE
и можете да си позволите разходите за производителност на допълнителния индекс, можете да създадете индекс в полето в DESC
поръчка.
Това е вярно за WHERE
клаузи, а не само ORDER BY
. Можете да използвате индекс на (a,b)
за търсене на WHERE a = 4
или WHERE a = 4 AND b = 3
но не за търсене на WHERE b = 3
сам.