sql >> Databasteknik >  >> RDS >> PostgreSQL

Vilken är ordningen på poster i en tabell med en sammansatt primärnyckel

Denna fråga gör det missriktade antagandet att primärnyckeln överhuvudtaget inför en tabellordning. Det gör det inte. PostgreSQL-tabeller har ingen definierad ordning, med eller utan en primärnyckel; de är en "hög" av rader ordnade i sidblock. Beställning åläggs med ORDER BY klausul av frågor när så önskas.

Du kanske tänker att PostgreSQL-tabeller lagras som indexorienterade tabeller som lagras på disken i primärnyckelordning, men det är inte så Pg fungerar. Jag tror att InnoDB lagrar tabeller organiserade efter primärnyckeln (men har inte markerat), och det är valfritt i vissa andra leverantörers databaser med en funktion som ofta kallas "klustrade index" eller "indexorganiserade tabeller". Den här funktionen stöds för närvarande inte av PostgreSQL (åtminstone från 9.3).

Som sagt, den PRIMARY KEY implementeras med en UNIQUE index, och det finns en ordning på det indexet. Den sorteras i stigande ordning från den vänstra kolumnen i indexet (och därmed primärnyckeln) och framåt, som om det vore ORDER BY col1 ASC, col2 ASC, col3 ASC; . Detsamma gäller för alla andra b-träd (till skillnad från GiST eller GIN) index i PostgreSQL, eftersom de är implementerade med b+träd.

Så i tabellen:

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

systemet kommer automatiskt att skapa motsvarigheten till:

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

Detta rapporteras till dig när du skapar en tabell, t.ex.:

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

Du kan se detta index när du granskar tabellen:

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)

Du kan CLUSTER på detta index för att ordna om tabellen enligt primärnyckeln, men det är en engångsoperation. Systemet upprätthåller inte den ordningen – dock om det finns ledigt utrymme på sidorna på grund av en FILLFACTOR som inte är standard Jag tror att det kommer att försöka.

En konsekvens av indexets inneboende ordning (men inte högen) är att det är mycket snabbare att söka efter:

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

än:

SELECT * FROM demo ORDER BY a DESC, b;

och ingen av dessa kan använda primärnyckelindexet alls, de kommer att göra en seqscan om du inte har ett index på b :

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

Detta beror på att PostgreSQL kan använda ett index på (a,b) nästan lika snabbt som ett index på (a) ensam. Den kan inte använda ett index på (a,b) som om det vore ett index på (b) ensam - inte ens långsamt, det går bara inte.

När det gäller DESC för att en Pg måste göra en omvänd indexskanning, som är långsammare än en vanlig framåtindexavsökning. Om du ser många omvända indexsökningar i EXPLAIN ANALYZE och du har råd med prestandakostnaden för det extra indexet, du kan skapa ett index på fältet i DESC beställa.

Detta gäller för WHERE satser, inte bara ORDER BY . Du kan använda ett index på (a,b) för att söka efter WHERE a = 4 eller WHERE a = 4 AND b = 3 men inte för att söka efter WHERE b = 3 ensam.




  1. Är det bättre att skapa ett index innan du fyller en tabell med data, eller efter att data är på plats?

  2. Varför är logiska läsningar för aggregerade fönsterfunktioner så höga?

  3. SQL-uppdatering översta radens fråga

  4. Introduktion till PostgreSQL