PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Qual é a ordem dos registros em uma tabela com uma chave primária composta


Esta questão faz a suposição equivocada de que a chave primária impõe uma ordem de tabela. Não. As tabelas do PostgreSQL não têm ordem definida, com ou sem chave primária; eles são um "heap" de linhas organizadas em blocos de página. A ordenação é imposta usando o ORDER BY cláusula de consultas quando desejado.

Você pode estar pensando que as tabelas do PostgreSQL são armazenadas como tabelas orientadas a índices que são armazenadas no disco em ordem de chave primária, mas não é assim que o Pg funciona. Eu acho que o InnoDB armazena tabelas organizadas pela chave primária (mas não verifiquei), e é opcional em bancos de dados de outros fornecedores usando um recurso geralmente chamado de "índices agrupados" ou "tabelas organizadas por índice". Este recurso não é suportado atualmente pelo PostgreSQL (pelo menos a partir de 9.3).

Dito isso, a PRIMARY KEY é implementado usando um UNIQUE index, e há uma ordenação para esse índice. Ele é classificado em ordem crescente da coluna esquerda do índice (e, portanto, da chave primária) em diante, como se fosse ORDER BY col1 ASC, col2 ASC, col3 ASC; . O mesmo vale para qualquer outro índice b-tree (diferente de GiST ou GIN) no PostgreSQL, pois eles são implementados usando b+trees.

Então na tabela:
CREATE TABLE demo (
   a integer,
   b text, 
   PRIMARY KEY(a,b)
);

o sistema criará automaticamente o equivalente a:
CREATE UNIQUE INDEX demo_pkey ON demo(a ASC, b ASC);

Isso é relatado a você quando você cria uma tabela, por exemplo:
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

Você pode ver este índice ao examinar a tabela:
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)

Você pode CLUSTER neste índice para reordenar a tabela de acordo com a chave primária, mas é uma operação única. O sistema não manterá essa ordem - embora se houver espaço livre nas páginas devido a um FILLFACTOR não padrão Acho que vai tentar.

Uma consequência da ordenação inerente do índice (mas não do heap) é que ele é muito mais rápido para pesquisar:
SELECT * FROM demo ORDER BY a, b;
SELECT * FROM demo ORDER BY a;

que:
SELECT * FROM demo ORDER BY a DESC, b;

e nenhum deles pode usar o índice de chave primária, eles farão um seqscan, a menos que você tenha um índice em b :
SELECT * FROM demo ORDER BY b, a;
SELECT * FROM demo ORDER BY b;

Isso ocorre porque o PostgreSQL pode usar um índice em (a,b) quase tão rápido quanto um índice em (a) sozinho. Ele não pode usar um índice em (a,b) como se fosse um índice em (b) sozinho - nem mesmo devagar, simplesmente não pode.

Quanto ao DESC entrada, para esse Pg deve fazer uma varredura de índice reverso, que é mais lenta do que uma varredura de índice direta comum. Se você estiver vendo muitas varreduras de índice reverso em EXPLAIN ANALYZE e você pode arcar com o custo de desempenho do índice extra, você pode criar um índice no campo em DESC pedido.

Isso vale para WHERE cláusulas, não apenas ORDER BY . Você pode usar um índice em (a,b) para pesquisar WHERE a = 4 ou WHERE a = 4 AND b = 3 mas não para pesquisar WHERE b = 3 sozinho.