sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Cuál es el orden de los registros en una tabla con una clave primaria compuesta?

Esta pregunta hace la suposición equivocada de que la clave principal impone un orden de tabla en absoluto. no lo hace Las tablas de PostgreSQL no tienen un orden definido, con o sin clave principal; son un "montón" de filas dispuestas en bloques de páginas. La ordenación se impone mediante el ORDER BY cláusula de consultas cuando se desee.

Podría estar pensando que las tablas de PostgreSQL se almacenan como tablas orientadas a índices que se almacenan en el disco en orden de clave principal, pero no es así como funciona Pg. Creo que InnoDB almacena tablas organizadas por la clave principal (pero no lo he verificado), y es opcional en las bases de datos de otros proveedores que usan una característica a menudo llamada "índices agrupados" o "tablas organizadas por índice". Esta función no es compatible actualmente con PostgreSQL (al menos a partir de la versión 9.3).

Dicho esto, la PRIMARY KEY se implementa usando un UNIQUE índice, y hay un orden para ese índice. Se ordena de forma ascendente desde la columna izquierda del índice (y por tanto de la clave principal) en adelante, como si fuera ORDER BY col1 ASC, col2 ASC, col3 ASC; . Lo mismo se aplica a cualquier otro índice b-tree (a diferencia de GiST o GIN) en PostgreSQL, ya que se implementan mediante b+trees.

Entonces en la tabla:

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

el sistema creará automáticamente el equivalente de:

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

Esto se le informa cuando crea una tabla, por ejemplo:

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

Puede ver este índice al examinar la tabla:

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)

Puedes CLUSTER en este índice para reordenar la tabla según la clave principal, pero es una operación única. El sistema no mantendrá ese orden, aunque si hay espacio libre en las páginas debido a un FILLFACTOR no predeterminado Creo que lo intentará.

Una consecuencia del orden inherente del índice (pero no del montón) es que es mucho más rápido para buscar:

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

que:

SELECT * FROM demo ORDER BY a DESC, b;

y ninguno de estos puede usar el índice de clave principal en absoluto, harán un escaneo de secuencias a menos que tenga un índice en b :

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

Esto se debe a que PostgreSQL puede usar un índice en (a,b) casi tan rápido como un índice en (a) solo. No puede usar un índice en (a,b) como si fuera un índice en (b) solo, ni siquiera lentamente, simplemente no puede.

En cuanto a la DESC entrada, para ese Pg debe hacer un escaneo de índice inverso, que es más lento que un escaneo de índice directo ordinario. Si ve muchos escaneos de índice inverso en EXPLAIN ANALYZE y puede pagar el costo de rendimiento del índice adicional, puede crear un índice en el campo en DESC orden.

Esto es cierto para WHERE cláusulas, no solo ORDER BY . Puede usar un índice en (a,b) para buscar WHERE a = 4 o WHERE a = 4 AND b = 3 pero no para buscar WHERE b = 3 solo.