2017-08-09 84 views
1

我试图创建一个表,其中,第二列是有序的下降复合主键:使用ASC或DESC命令的主键?

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

这根本没有意义。您在选择时指定您的订单,而不是在索引时指定。另外,为了使用索引,您需要先通过'AccountNumber'命令,然后按'ts'命令,否则排序效率不高。为了克服这个问题,只在'ts'上指定一个单独的索引。但是,您不能在索引上指定排序顺序,仅限于选择。 – Psi

+0

@Psi你当然可以告诉postgresql索引列的顺序,这在很多情况下非常有意义,例如'create index myindex(AccountNumber,ts DESC)'在postgresql中有效,但我不确定是否它可以在主键上完成。 – nos

+0

@nos你可以自己指定索引列的顺序(例如'col B',然后'col A'),但是对于我来说这完全没有意义,为什么你可以颠倒特定列的索引顺序。另外我不明白你为什么要这样做,因为你想要选择而不是定义索引。您只能按升序或降序进行排序,这只是从开始或结束(然后向后)读取索引,因此不需要指定任何顺序来存储索引。 – Psi

回答

1

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

索引但不能是表的主键,但对于像

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

我认为这样做是合理的,因为语义上按升序或降序排列的索引是相同的,但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的行为。这可能对你很好。