我有很大的表消息。它包含大约100mil的记录。
当我运行简单查询时:
select uid from messages order by uid asc limit 1000
结果很奇怪。从一开始的记录是可以的,但是它们并不总是按列 uid 排序。
uid
----------
94621458
94637590
94653611
96545014
96553145
96581957
96590621
102907437
.....
446131576
459475933
424507749
424507166
459474125
431059132
440517049
446131301
475651666
413687676
.....
这是分析
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
答案 0 :(得分:2)
这是一个非常一般的答案:
尝试:
SET enable_indexscan TO off;
在同一会话中重新运行查询。
如果结果的顺序与enable_indexscan
到on
的顺序不同,则索引已损坏。
在这种情况下,请使用以下命令修复:
REINDEX INDEX index_name;
答案 1 :(得分:1)
您可以节省很长时间等待尝试在没有索引的情况下运行查询。问题很可能是由于索引损坏。立即修复它,看看是否能解决问题。
由于您的表格为is always under high load
,请考虑同时构建新索引。这需要更长的时间,但不会阻止并发写入。 Per documentation on REINDEX
:
要在不干扰生产的情况下构建索引,您应该删除 索引并重新发出
CREATE INDEX CONCURRENTLY
命令。
在CREATE INDEX
下:
CONCURRENTLY
使用此选项时,PostgreSQL将在不使用的情况下构建索引 采取任何阻止并发插入,更新或删除的锁 在桌子上;而标准索引构建会锁定写入(但不会 在桌面上读取,直到完成。有几点需要注意 了解何时使用此选项 - 请参阅Building Indexes 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;
最后一步只是对系统目录的微小更新。