Този въпрос прави погрешното предположение, че първичният ключ изобщо налага ред на таблицата. Не е така. 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 сам.