PostgreSQL 索引坏块一例

今天应用反应有张表查询报错,报错信息如下

1
2
back=# select max(create_time) from public.tbl_index_table where create_time>='2010-10-08';  
ERROR: could not read block 41381 of relation 16779/24769/24938: read only 0 of 8192 bytes

看到这个错误信息,首先想到的是表 tbl_index_table 上有坏块,估计需要表重建下。

查看执行计划

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
back=# /d tbl_index_table;  
Table "public.tbl_index_table"
Column | Type | Modifiers
----------------+-----------------------------+------------------------
total | integer |
logined | integer |
logining | integer |
http | integer |
rawtcp | integer |
create_time | timestamp without time zone | not null default now()
logincountdesc | character varying |
logincountaddr | character varying | not null
Indexes:
"tbl_index_table_pkey" PRIMARY KEY, btree (create_time, logincountaddr)
"index_tbl_index_table_create_time" btree (create_time)

back=# select max(create_time) from public.tbl_index_table where create_time>='2010-10-08';
ERROR: could not read block 41381 of relation 16779/24769/24938: read only 0 of 8192 bytes

back=# explain select max(create_time) from public.tbl_index_table where create_time>='2010-10-08';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
Result (cost=0.04..0.05 rows=1 width=0)
InitPlan
-> Limit (cost=0.00..0.04 rows=1 width=8)
-> Index Scan Backward using index_tbl_index_table_create_time on tbl_index_table (cost=0.00..66.28 rows=1507 width=8)
Index Cond: (create_time >= '2010-10-08 00:00:00'::timestamp without time zone)
Filter: (create_time IS NOT NULL)
(6 rows)

发现上面的查询走的索引 index_tbl_index_table_create_time,猜测索引可能有问题。

根据报错信息,从relation后面的数字分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
back=# select oid,relname from pg_class where oid=24938;  
oid | relname
-------+-----------------------------------------
24938 | index_tbl_index_table_create_time
(1 row)
Time: 0.596 ms

back=# select oid,relname from pg_class where oid=24769;
oid | relname
-----+---------
(0 rows)
Time: 0.369 ms

back=# select oid,relname from pg_class where oid=16779;
oid | relname
-----+---------
(0 rows)

发现 24938正好是表上的索引 index_tbl_index_table_create_time。

查看索引状态

1
2
3
4
5
back=# select * from pg_index where indexrelid=24938;  
indexrelid | indrelid | indnatts | indisunique | indisprimary | indisclustered | indisvalid | indcheckxmin | indisready | indkey | indclass | indoption | indexprs | indpred
------------+----------+----------+-------------+--------------+----------------+------------+--------------+------------+--------+----------+-----------+----------+---------
24938 | 24823 | 1 | f | f | f | t | f | t | 6 | 10053 | 0 | |
(1 row)

indisvalid=t 表示索引处于可用状态。

尝试重建索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
back=# select current_query from pg_stat_activity;  
current_query
---------------------------------------------
<IDLE>
<IDLE>
select current_query from pg_stat_activity;
<IDLE>
<IDLE>
(22 rows)

back=# timing
Timing is on.

back=# reindex index index_tbl_index_table_create_time;
REINDEX
Time: 107796.232 ms

索引重建后,查询恢复正常

1
2
3
4
5
6
7
8
9
10
11
12
back=# select max(create_time) from public.tbl_index_table where create_time>='2010-10-08';  
max
-----

(1 row)
Time: 73.600 ms

back=# select pg_size_pretty(pg_relation_size('index_tbl_index_table_create_time'));
pg_size_pretty
----------------
327 MB
(1 row)

总结

网上查了下,说是 Postgresql 的bug 2197, 但从上面的处理过程来看,应该是索引上有坏块,索引重建后,查询恢复正常。

原创文章,作者:bd101bd101,如若转载,请注明出处:https://blog.ytso.com/tech/database/236333.html

(0)
上一篇 2022年1月24日 21:26
下一篇 2022年1月24日 21:26

相关推荐

发表回复

登录后才能评论