有没有办法自动按主键对 PostgreSQL 表进行排序?

pet*_*erh 4 postgresql primary-key

我想转储一个表的全部内容,按主键排序。直觉上,我想做一个

SELECT * FROM %table_name% ORDER BY %primary_key_of(table_name)%;
Run Code Online (Sandbox Code Playgroud)

这将由外部工具运行,知道表的列表,但不知道它们的主键。

如果没有更好的选择,我们可以假设所有的主键都是单列的。

我使用的是 PostgreSQL-9.5,但可以升级。

Evg*_*rev 5

默认情况下, simpleSELECT * FROM %table_name%不会按主键对结果进行排序。

但是您可以获得表的主键列列表:

SELECT ind_column.attname AS columns_of_pk
FROM pg_class tbl
  INNER JOIN pg_index ind ON ind.indrelid = tbl.oid
  INNER JOIN pg_class ind_table ON ind_table.oid = ind.indexrelid
  INNER JOIN pg_attribute ind_column ON ind_column.attrelid = ind_table.oid
WHERE tbl.relname = 'my_table'
  AND ind.indisprimary;
Run Code Online (Sandbox Code Playgroud)

然后在ORDER BY子句中使用此列构建动态查询。

如果在不同模式中有多个同名表,请添加INNER JOIN pg_namespace sch ON sch.oid = tbl.relnamespace并设置WHERE条件sch.nspname

您可以在 1 个查询中获取所有表的 PK:

SELECT sch.nspname AS "schema"
  , tbl.relname AS "table"
  , array_agg(ind_column.attname) AS columns_of_pk
FROM pg_class tbl
  INNER JOIN pg_namespace sch ON sch.oid = tbl.relnamespace
  INNER JOIN pg_index ind ON ind.indrelid = tbl.oid
  INNER JOIN pg_class ind_table ON ind_table.oid = ind.indexrelid
  INNER JOIN pg_attribute ind_column ON ind_column.attrelid = ind_table.oid
WHERE sch.nspname <> 'pg_toast'
  AND ind.indisprimary
GROUP BY "schema", "table";
Run Code Online (Sandbox Code Playgroud)


Nei*_*gan 1

我相信如果你在主键上放置聚集索引,那么 PG 将默认使用它。未经检验的假设:)

CLUSTER table_name USING primary_key_index;
Run Code Online (Sandbox Code Playgroud)

根据https://www.postgresql.org/docs/current/static/sql-cluster.html

如果您随机访问表中的单行,则表中数据的实际顺序并不重要。但是,如果您倾向于比其他数据更频繁地访问某些数据,并且有一个索引将它们分组在一起,那么您将从使用 CLUSTER 中受益。如果您要从表中请求一系列索引值,或者请求具有多个匹配行的单个索引值,则 CLUSTER 将有所帮助,因为一旦索引识别出匹配的第一行的表页,则所有其他匹配的行都可能是已经在同一个表页上,因此您可以节省磁盘访问并加快查询速度。

CLUSTER 可以使用指定索引上的索引扫描或(如果索引是 B 树)顺序扫描然后排序来对表重新排序。它将尝试根据规划器成本参数和可用的统计信息选择更快的方法。

  • 只要您不提供“ORDER BY”,就绝对不能保证结果是顺序的。如果没有“ORDER BY”,“集群”表**不**保证任何结果排序。获得排序结果的**唯一**方法是使用`ORDER BY`,没有其他选择 (5认同)