主键数组中键的顺序重要吗?

Does the order of keys in a primary key array matter?

我们有一个 distributed/sharded 数据库,所以我们使用 idpartner_id(这是我们的分区 ID)的组合作为我们任何分布式数据库的主键表。

在我的 schema.rb 文件中,此声明如下所示:

create_table "back_in_stock_subscriptions", primary_key: ["id", "partner_id"], force: :cascade do |t|

导致我提出问题的问题是,当我的一位同事 运行 迁移时,架构被修改为如下所示:

create_table "back_in_stock_subscriptions", primary_key: ["partner_id", "id"], force: :cascade do |t|

因此,无论何时他们 运行 迁移,他们都必须分阶段提交他们实际添加到数据库中的部分,然后丢弃对 schema.rb 文件的剩余更改。或者,如果他们正在 运行ning 其他人添加的迁移,他们只会完全放弃 schema.rb 更改。当然,这是一个非常小的麻烦,我不知道为什么会这样,但它有点令人担忧。

所以我的问题是这重要吗?如果他不小心让其中一个“逆转”滑入了提交,那会不会有什么大不了的(除了下次我 运行 迁移时,它会逆转它)?

一个测试用例:

create table pk_test1 (id integer, id2 integer, primary key(id, id2));
create table pk_test1 (id integer, id2 integer, primary key(id2, id));

\d pk_test
              Table "public.pk_test"
 Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+---------
 id     | integer |           | not null | 
 id2    | integer |           | not null | 
Indexes:
    "pk_test_pkey" PRIMARY KEY, btree (id, id2)

\d pk_test2
              Table "public.pk_test2"
 Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+---------
 id     | integer |           | not null | 
 id2    | integer |           | not null | 
Indexes:
    "pk_test2_pkey" PRIMARY KEY, btree (id2, id)


insert into pk_test values (1, 2), (2,1);
insert into pk_test2 values (1, 2), (2,1);

select * from pk_test;
 id | id2 
----+-----
  1 |   2
  2 |   1
(2 rows)

test(5432)=# select * from pk_test2;
 id | id2 
----+-----
  1 |   2
  2 |   1

insert into pk_test values (1, 2);
ERROR:  duplicate key value violates unique constraint "pk_test_pkey"
DETAIL:  Key (id, id2)=(1, 2) already exists.

insert into pk_test2 values (1, 2);
ERROR:  duplicate key value violates unique constraint "pk_test2_pkey"
DETAIL:  Key (id2, id)=(2, 1) already exists.

--THE PROBLEM

create table pk_child_tbl (child_id integer, parent_id integer, parent_id2 integer, foreign key(parent_id, parent_id2) references pk_test2);

insert into pk_test2 values (3,2);

 select * from pk_test2;
 id | id2 
----+-----
  1 |   2
  2 |   1
  3 |   2

 \d pk_test2
              Table "public.pk_test2"
 Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+---------
 id     | integer |           | not null | 
 id2    | integer |           | not null | 
Indexes:
    "pk_test2_pkey" PRIMARY KEY, btree (id2, id)
Referenced by:
    TABLE "pk_child_tbl" CONSTRAINT "pk_child_tbl_parent_id_parent_id2_fkey" FOREIGN KEY (parent_id, parent_id2) REFERENCES pk_test2(id2, id)


insert into pk_child_tbl values (2, 3, 2);
ERROR:  insert or update on table "pk_child_tbl" violates foreign key constraint "pk_child_tbl_parent_id_parent_id2_fkey"
DETAIL:  Key (parent_id, parent_id2)=(3, 2) is not present in table "pk_test2".

如果您有仅指向父 table 的外键引用,而没有指定父 table 列的顺序,它将选取主键顺序和子 parent_id/parent_id2字段将不再匹配父 table id/id2 订单。

就唯一性而言,主键定义中列的顺序无关紧要。

但是主键总是通过唯一索引实现的,并且该索引可用于加速查询。为此,列的顺序可能很重要。例如,此查询:

SELECT * FROM tab WHERE col1 = 42;

可以使用 (col1, col2) 上的主键索引,但不能使用 (col2, col1) 上的主键索引。