Postgresql Postgres以错误的顺序返回记录

Postgresql Postgres以错误的顺序返回记录,postgresql,indexing,sql-order-by,corruption,Postgresql,Indexing,Sql Order By,Corruption,我有相当大的表信息。它包含大约100mil记录 运行简单查询时: select uid from messages order by uid asc limit 1000 结果很奇怪。开始时的记录是可以的,但是它们并不总是按列uid排序 这里是分析 Limit (cost=0.00..3740.51 rows=1000 width=4) (actual time=0.009..4.630 rows=1000 loops=1) Output: uid -> Index S

我有相当大的表信息。它包含大约100mil记录

运行简单查询时:

select uid from messages order by uid asc limit 1000
结果很奇怪。开始时的记录是可以的,但是它们并不总是按列uid排序

这里是分析

 Limit  (cost=0.00..3740.51 rows=1000 width=4) (actual time=0.009..4.630 rows=1000 loops=1)
   Output: uid
   ->  Index Scan using messages_pkey on public.messages  (cost=0.00..376250123.91 rows=100587944 width=4) (actual time=0.009..4.150 rows=1000 loops=1)
         Output: uid
 Total runtime: 4.796 ms
PostgreSQL 9.1.12

该表始终处于高负载(插入、更新、删除)下,并且几乎一直处于自动清空状态。这会导致问题吗

UPD。添加了表定义。抱歉,无法添加完整的表定义,但所有重要字段及其类型都在此处

# \d+ messages
                                                   Table "public.messages"
    Column    |            Type             |                       Modifiers                        | Storage  | Description
--------------+-----------------------------+--------------------------------------------------------+----------+-------------
 uid          | integer                     | not null default nextval('messages_uid_seq'::regclass) | plain    |
 code         | character(22)               | not null                                               | extended |
 created      | timestamp without time zone | not null                                               | plain    |
 accountid    | integer                     | not null                                               | plain    |
 status       | character varying(20)       | not null                                               | extended |
 hash         | character(3)                | not null                                               | extended |
 xxxxxxxx     | timestamp without time zone | not null                                               | plain    |
 xxxxxxxx     | integer                     |                                                        | plain    |
 xxxxxxxx     | character varying(255)      |                                                        | extended |
 xxxxxxxx     | text                        | not null                                               | extended |
 xxxxxxxx     | character varying(250)      | not null                                               | extended |
 xxxxxxxx     | text                        |                                                        | extended |
 xxxxxxxx     | text                        | not null                                               | extended |
Indexes:
    "messages_pkey" PRIMARY KEY, btree (uid)
    "messages_unique_code" UNIQUE CONSTRAINT, btree (code)
    "messages_accountid_created_idx" btree (accountid, created)
    "messages_accountid_hash_idx" btree (accountid, hash)
    "messages_accountid_status_idx" btree (accountid, status)
Has OIDs: no

下面是一个非常笼统的答案:

尝试:

在同一会话中重新运行查询

如果结果的顺序与启用索引扫描时的顺序不同,则索引已损坏

在这种情况下,请使用以下方法进行修复:

REINDEX INDEX index_name;

避免在没有索引的情况下运行查询的漫长等待。问题很可能是由于索引已损坏。马上修理,看看是否能解决问题

因为您的表总是在高负载< /代码>下,考虑同时构建一个新索引。耗时稍长,但不会阻止并发写入

为了在不影响生产的情况下建立索引,您应该 索引并同时重新发出
创建索引
命令

以及在下列情况下:

使用此选项时,PostgreSQL将在不使用 获取任何阻止并发插入、更新或删除的锁 在桌子上;而标准索引构建会锁定写操作(但不会 阅读)放在桌子上直到完成。有几点需要注意 知道何时使用此选项-请参阅

因此,我建议:

ALTER TABLE news DROP CONSTRAINT messages_pkey;
CREATE UNIQUE INDEX CONCURRENTLY messages_pkey ON news (uid);
ALTER TABLE news ADD PRIMARY KEY USING INDEX messages_pkey;

最后一步只是对系统目录的一个小小的更新。

您是按字面意思记录的吗
[space]965…
?如果是这样的话,它们很可能是按字符串排序的,空格比数字“低”。如果您按uid:int进行排序,是否有区别?您的表定义在这里是必须的。我们需要查看
uid
的数据类型。在psql中发布您通过
\d消息获得的信息。谢谢。添加了表定义您使用什么程序来运行此查询?好的,我使用indexscan=off启动了查询,但此表中有100mil记录,因此需要很长时间才能完成查询。似乎您是对的。在indexscan=关闭的情况下,结果是正确的。谢谢你创建索引是我不相信的一种魔法。特别是在实时服务器上。我认为最好在复制服务器上清空整个表,然后将应用程序的路由切换到数据库。真空吸尘器会帮上大忙吗?@neon你为什么不相信同时创建索引呢?你有任何证据证明它不起作用吗?
REINDEX INDEX index_name;
CONCURRENTLY
ALTER TABLE news DROP CONSTRAINT messages_pkey;
CREATE UNIQUE INDEX CONCURRENTLY messages_pkey ON news (uid);
ALTER TABLE news ADD PRIMARY KEY USING INDEX messages_pkey;