1

我正在使用 PostgreSQL 8.4.13 数据库。
最近我在一个表中有大约 8650 万条记录。我几乎全部删除了——现在只剩下 5000 条记录。我跑了:

vacuum full

在删除行并将磁盘空间返回给操作系统之后(感谢 SO 成员的建议

但我看到我的身份证号码仍然停留在数百万。例如:

    id   |        date_time        | event_id | secs_since_1970 |    value 
---------+-------------------------+----------+-----------------+-----------
61216287 | 2013/03/18 16:42:42:041 |        6 |   1363646562.04 |   46.4082
61216289 | 2013/03/18 16:42:43:041 |        6 |   1363646563.04 |   55.4496
61216290 | 2013/03/18 16:42:44:041 |        6 |   1363646564.04 |   40.0553
61216291 | 2013/03/18 16:42:45:041 |        6 |   1363646565.04 |   38.5694

为了尝试重新开始剩余行的id值,我尝试了:1

cluster mytable_pkey on mytable;

mytable我的桌子的名字在哪里。但这并没有帮助。所以,我的问题是/是:

  1. 有没有办法让索引(id 值)再次从 1 开始?
  2. 如果我使用新记录添加或更新表,它会从 1 开始还是选择下一个最高整数值(例如上面示例中的 61216292)?

我的表描述如下:里面没有FK约束,也没有序列。

jbossql=> \d mytable;
           Table "public.mytable"
 Column      |          Type          | Modifiers 
-----------------+------------------------+-----------
 id              | bigint                 | not null
 date_time       | character varying(255) | 
 event_id        | bigint                 | 
 secs_since_1970 | double precision       | 
 value           | real                   | 
Indexes:
    "mydata_pkey" PRIMARY KEY, btree (id) CLUSTER
4

3 回答 3

2

您的主键是使用序列号定义的吗?如果是这样,则会创建一个隐式序列。您可以使用 ALTER SEQUENCE(有关语法,请参见:http ://www.postgresql.org/docs/8.2/static/sql-altersequence.html )将起始编号更改回 1。

基于您还剩下一些记录的事实(只注意到剩下的 5000 条),您不想将该数字重置为剩余记录的最后一个 ID 之前的数字,因为那样该序列将生成非唯一数字。使用序列的意义在于,它为您提供了一种递增数字的事务方式,并保证连续操作获得唯一的递增数字。

于 2013-03-20T15:21:26.977 回答
2
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;

        --
        -- Note: "deferrable initially deferred" appears to be the default
        --
CREATE TABLE funky
        ( id SERIAL NOT NULL PRIMARY KEY DEFERRABLE INITIALLY DEFERRED
        , tekst varchar
        );
        -- create some data with gaps in it
INSERT INTO funky(id, tekst)
SELECT  gs, 'Number:' || gs::text
FROM generate_series(1,100,10) gs
        ;

        -- set the sequence to the max occuring id
SELECT setval('funky_id_seq' , mx.mx)
FROM (SELECT max(id) AS mx FROM funky) mx
        ;

SELECT * FROM funky ;

        -- compress the keyspace, making the ids consecutive
UPDATE funky xy
SET id =  self.newid
FROM (
        SELECT id AS id
        , row_number() OVER (ORDER BY id) AS newid
        FROM funky
        ) self
WHERE self.id = xy.id
        ;

        -- set the sequence to the new max occuring id
SELECT setval('funky_id_seq' , mx.mx)
FROM (SELECT max(id) AS mx FROM funky) mx
        ;

SELECT * FROM funky ;

结果:

CREATE TABLE
INSERT 0 10
 setval 
--------
     91
(1 row)

 id |   tekst   
----+-----------
  1 | Number:1
 11 | Number:11
 21 | Number:21
 31 | Number:31
 41 | Number:41
 51 | Number:51
 61 | Number:61
 71 | Number:71
 81 | Number:81
 91 | Number:91
(10 rows)

UPDATE 10
 setval 
--------
     10
(1 row)

 id |   tekst   
----+-----------
  1 | Number:1
  2 | Number:11
  3 | Number:21
  4 | Number:31
  5 | Number:41
  6 | Number:51
  7 | Number:61
  8 | Number:71
  9 | Number:81
 10 | Number:91
(10 rows)

警告 警告 警告 警告 警告 ACHTUNG:

更改键值通常是一个糟糕的主意。不惜一切代价避免它。

于 2013-03-20T15:47:22.310 回答
2

首先删除主键并创建一个临时序列。

alter table mytable drop constraint mydata_pkey;
create temporary sequence temp_seq;

使用序列更新:

update mytable
set id = nextval('temp_seq');

重新创建主键并删除序列

alter table mytable add primary key (id);
drop sequence temp_seq;

如果此表有外键依赖,那么您必须先处理它,更新将是一个更复杂的过程。

于 2013-03-21T11:31:39.363 回答