使用ASC或DESC排序的主键?

时间:2017-08-09 17:27:56

标签: postgresql

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

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

然而,PostgreSQL表示DESC子句存在语法错误。

  • PostgreSQL真的不允许这样做吗?
  • 拥有这样的DESC密钥是否有意义?
  • 我唯一的选择是使用我想要的语义创建一个额外的索引吗?

2 个答案:

答案 0 :(得分:2)

请参阅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);

但是这不能是桌面上的PRIMARY KEY,尽管对于像

这样的查询很重要
select DISTINCT on (accountnumber) * from AccountHistory
order by accountnumber,ts desc;

测试:

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)"

答案 1 :(得分:2)

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

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

ERROR:  index "foopk" does not have default sorting behavior

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

只需单独创建唯一索引,就可以获得PRIMARY KEY - 没有约束元数据的行为。那可能对你没问题。