sql >> Database >  >> RDS >> PostgreSQL

Wat is de volgorde van records in een tabel met een samengestelde primaire sleutel

Deze vraag maakt de misplaatste veronderstelling dat de primaire sleutel überhaupt een tabelvolgorde oplegt. Dat doet het niet. PostgreSQL-tabellen hebben geen gedefinieerde volgorde, met of zonder een primaire sleutel; ze zijn een "hoop" rijen gerangschikt in paginablokken. Bestelling wordt opgelegd met behulp van de ORDER BY clausule van vragen indien gewenst.

Je zou kunnen denken dat PostgreSQL-tabellen worden opgeslagen als index-georiënteerde tabellen die op schijf worden opgeslagen in de volgorde van de primaire sleutel, maar dat is niet hoe Pg werkt. Ik denk dat InnoDB tabellen opslaat die zijn geordend op de primaire sleutel (maar niet hebben gecontroleerd), en het is optioneel in de databases van sommige andere leveranciers met behulp van een functie die vaak "geclusterde indexen" of "index-georganiseerde tabellen" wordt genoemd. Deze functie wordt momenteel niet ondersteund door PostgreSQL (vanaf 9.3 tenminste).

Dat gezegd hebbende, de PRIMARY KEY wordt geïmplementeerd met behulp van een UNIQUE index, en er is een ordening voor die index. Het wordt in oplopende volgorde gesorteerd vanaf de linkerkolom van de index (en dus de primaire sleutel), alsof het ORDER BY col1 ASC, col2 ASC, col3 ASC; . Hetzelfde geldt voor elke andere b-tree-index (in tegenstelling tot GiST of GIN) in PostgreSQL, aangezien ze worden geïmplementeerd met behulp van b+trees.

Dus in de tabel:

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

het systeem maakt automatisch het equivalent van:

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

Dit wordt aan u gerapporteerd wanneer u een tabel aanmaakt, bijvoorbeeld:

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

U kunt deze index zien wanneer u de tabel bekijkt:

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)

U kunt CLUSTER op deze index om de tabel opnieuw te ordenen volgens de primaire sleutel, maar het is een eenmalige bewerking. Het systeem handhaaft die volgorde niet, maar als er ruimte vrij is op de pagina's vanwege een niet-standaard FILLFACTOR Ik denk dat het zal proberen.

Een gevolg van de inherente ordening van de index (maar niet de heap) is dat het veel is sneller zoeken naar:

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

dan:

SELECT * FROM demo ORDER BY a DESC, b;

en geen van beide kan de primaire sleutelindex gebruiken, ze zullen een seqscan doen, tenzij je een index hebt op b :

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

Dit komt omdat PostgreSQL een index kan gebruiken op (a,b) bijna net zo snel als een index op (a) alleen. Het kan geen index gebruiken op (a,b) alsof het een index is op (b) alleen - zelfs niet langzaam, het kan gewoon niet.

Wat betreft de DESC invoer, voor die ene Pg moet een reverse index-scan worden uitgevoerd, die langzamer is dan een gewone forward index-scan. Als u veel reverse index-scans ziet in EXPLAIN ANALYZE en u kunt de prestatiekosten van de extra index betalen u kunt een index maken op het veld in DESC bestellen.

Dit geldt voor WHERE clausules, niet alleen ORDER BY . U kunt een index gebruiken op (a,b) om te zoeken naar WHERE a = 4 of WHERE a = 4 AND b = 3 maar niet om te zoeken naar WHERE b = 3 alleen.




  1. Een enkel eindpunt maken voor uw PostgreSQL-replicatie-installatie met behulp van HAProxy

  2. Hoe strftime en datetime correct te gebruiken met behulp van de Room-bibliotheek?

  3. Vul ontbrekende datums in voor uitvoer van SQL Server-query's met behulp van CTE

  4. Wat is het verschil tussen utf8mb4- en utf8-tekensets in MySQL?