具有 ASC 或 DESC 排序的主键?

Mik*_*iss 6 postgresql

我正在尝试创建一个带有复合主键的表,其中第二列按降序排列:

CREATE TABLE AccountHistory (                                                                                                                                                                           
  AccountNumber BIGINT NOT NULL,                                                                                                                                                                        
  Ts TIMESTAMP NOT NULL,                                                                                                                                                                                
  Memo TEXT,                                                                                                                                                                                            
  ChangeAmount BIGINT NOT NULL,                                                                                                                                                                         
  PRIMARY KEY (AccountNumber, ts DESC)                                                                                                                                                              
);
Run Code Online (Sandbox Code Playgroud)

但是,PostgreSQL 表示该DESC子句存在语法错误。

  • PostgreSQL 真的不允许这样做吗?
  • 拥有这样的 DESC 键有意义吗?
  • 使用我想要的语义创建附加索引是我唯一的选择吗?

Cra*_*ger 6

我认为这样做是合理的,因为从语义上讲,升序或降序索引是相同的,但 PostgreSQL 不支持它。无法控制自动创建以支持主键的索引的索引顺序。

PostgreSQL 不会让您通过手动创建索引作为UNIQUE具有DESC排序顺序的索引然后PRIMARY KEY使用它创建声明的约束来创建一个ALTER TABLE ... ADD CONSTRAINT ... PRIMARY KEY USING INDEX ...。它将失败:

ERROR:  index "foopk" does not have default sorting behavior
Run Code Online (Sandbox Code Playgroud)

我不知道为什么 Pg 需要这个。搜索上述错误的源代码可能会为您找到合适的注释。

PRIMARY KEY只需单独创建唯一索引,您就可以在没有约束元数据的情况下获得类似行为。这对你来说可能没问题。


csk*_*ske 4

请参阅https://dba.stackexchange.com/questions/90722/is-unique-index-better-than-unique-constraint-when-an-index-with-an-operator-cla

您可以创建一个索引,例如

CREATE UNIQUE INDEX accounthistory_pk_2 on AccountHistory(AccountNumber, ts DESC);
Run Code Online (Sandbox Code Playgroud)

但这不能是表上的主键,尽管对于像这样的查询很重要

select DISTINCT on (accountnumber) * from AccountHistory
order by accountnumber,ts desc;
Run Code Online (Sandbox Code Playgroud)

测试:

CREATE TABLE AccountHistory (
  AccountNumber BIGINT NOT NULL,
  Ts TIMESTAMP NOT NULL,
  Memo TEXT,
  ChangeAmount BIGINT NOT NULL
);

EXPLAIN select DISTINCT on (accountnumber) * from AccountHistory
order by accountnumber,ts desc;

"Unique  (cost=65.82..70.52 rows=200 width=56)"
"  ->  Sort  (cost=65.82..68.17 rows=940 width=56)"
"        Sort Key: accountnumber, ts"
"        ->  Seq Scan on accounthistory  (cost=0.00..19.40 rows=940 width=56)"

set enable_seqscan=false;

"Unique  (cost=10000000065.82..10000000070.52 rows=200 width=56)"
"  ->  Sort  (cost=10000000065.82..10000000068.17 rows=940 width=56)"
"        Sort Key: accountnumber, ts"
"        ->  Seq Scan on accounthistory  (cost=10000000000.00..10000000019.40 rows=940 width=56)"

CREATE UNIQUE INDEX accounthistory_pk_1 on AccountHistory(AccountNumber, ts);

"Unique  (cost=10000000065.82..10000000070.52 rows=200 width=56)"
"  ->  Sort  (cost=10000000065.82..10000000068.17 rows=940 width=56)"
"        Sort Key: accountnumber, ts"
"        ->  Seq Scan on accounthistory  (cost=10000000000.00..10000000019.40 rows=940 width=56)"

CREATE UNIQUE INDEX accounthistory_pk_2 on AccountHistory(AccountNumber, ts DESC);

"Unique  (cost=0.15..60.60 rows=200 width=56)"
"  ->  Index Scan using accounthistory_pk_2 on accounthistory  (cost=0.15..58.25 rows=940 width=56)"
Run Code Online (Sandbox Code Playgroud)