PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Jaka jest kolejność rekordów w tabeli ze złożonym kluczem podstawowym?

To pytanie wprowadza błędne założenie, że klucz podstawowy w ogóle narzuca kolejność tabel. Nie. Tabele PostgreSQL nie mają zdefiniowanej kolejności, z kluczem podstawowym lub bez; są „stosem” wierszy ułożonych w bloki stron. Zamówienie jest narzucane za pomocą ORDER BY klauzula zapytań w razie potrzeby.

Możesz myśleć, że tabele PostgreSQL są przechowywane jako tabele zorientowane na indeks, które są przechowywane na dysku w kolejności klucza podstawowego, ale tak nie działa Pg. Myślę, że InnoDB przechowuje tabele zorganizowane według klucza podstawowego (ale nie zostały sprawdzone) i jest opcjonalne w bazach danych niektórych innych dostawców przy użyciu funkcji często nazywanej „indeksy klastrowe” lub „tabele zorganizowane według indeksów”. Ta funkcja nie jest obecnie obsługiwana przez PostgreSQL (przynajmniej od wersji 9.3).

To powiedziawszy, PRIMARY KEY jest zaimplementowany przy użyciu UNIQUE indeks i istnieje kolejność tego indeksu. Jest sortowany w porządku rosnącym od lewej kolumny indeksu (a zatem od klucza podstawowego) dalej, tak jakby był ORDER BY col1 ASC, col2 ASC, col3 ASC; . To samo dotyczy każdego innego indeksu b-drzewa (w odróżnieniu od GiST lub GIN) w PostgreSQL, ponieważ są one zaimplementowane przy użyciu b+drzewa.

Więc w tabeli:

CREATE TABLE demo (
   a integer,
   b text, 
   PRIMARY KEY(a,b)
);

system automatycznie utworzy odpowiednik:

CREATE UNIQUE INDEX demo_pkey ON demo(a ASC, b ASC);

Jest to zgłaszane podczas tworzenia tabeli, np.:

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

Możesz zobaczyć ten indeks podczas sprawdzania tabeli:

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)

Możesz CLUSTER na tym indeksie, aby zmienić kolejność tabeli zgodnie z kluczem podstawowym, ale jest to jednorazowa operacja. System nie utrzyma tej kolejności - chociaż jeśli na stronach jest wolne miejsce z powodu niedomyślnego FILLFACTOR Myślę, że spróbuje.

Jedną z konsekwencji nieodłącznej kolejności indeksu (ale nie sterty) jest to, że jest dużo szybsze wyszukiwanie:

SELECT * FROM demo ORDER BY a, b;
SELECT * FROM demo ORDER BY a;

niż:

SELECT * FROM demo ORDER BY a DESC, b;

i żaden z nich nie może w ogóle używać indeksu klucza podstawowego, wykonają seqscan, chyba że masz indeks na b :

SELECT * FROM demo ORDER BY b, a;
SELECT * FROM demo ORDER BY b;

Dzieje się tak, ponieważ PostgreSQL może używać indeksu w (a,b) prawie tak szybko, jak indeks na (a) sam. Nie może używać indeksu w (a,b) jakby to był indeks na (b) sam - nawet nie wolno, po prostu nie może.

Co do DESC wpis, dla tego jednego Pg musi wykonać skanowanie indeksu wstecznego, które jest wolniejsze niż zwykłe skanowanie indeksu w przód. Jeśli widzisz wiele skanów odwrotnego indeksu w EXPLAIN ANALYZE i możesz sobie pozwolić na koszt wydajności dodatkowego indeksu, możesz utworzyć indeks w polu w DESC zamówienie.

Dotyczy to WHERE klauzul, nie tylko ORDER BY . Możesz użyć indeksu na (a,b) aby wyszukać WHERE a = 4 lub WHERE a = 4 AND b = 3 ale nie aby wyszukać WHERE b = 3 sam.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak korzystać z LoggingConnection firmy Psycopg2?

  2. CTE i paradoks urodzin

  3. Używanie logicznej replikacji PostgreSQL do utrzymywania zawsze aktualnego serwera TEST do odczytu/zapisu

  4. Jak zachować dane w zadokowanej bazie danych postgres przy użyciu woluminów?

  5. Wielokrotne wywołanie funkcji zwracającej zestaw z argumentem tablicowym