记录一则PostgreSQL数据库主键索引不生效的案例
Contents
一 背景说明
一则生产环境的慢SQL,发现日志表上没有任何索引,且数据量也不小,300多万条记录,走的全表扫描的执行计划,通过主键id查询数据耗时4秒多。
数据库是PostgreSQL 9.6,运行在CentOS 7.6的系统上,48颗 CPU、内存64GB。
[root@primarydb ~]# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
[root@primarydb ~]# free -m
total used free shared buff/cache available
Mem: 63883 5077 3665 19767 55141 38095
Swap: 16379 843 15536
[root@primarydb ~]# su - postgres
Last login: Sat May 7 08:42:26 CST 2022 on pts/2
[postgres@primarydb ~]$ psql
psql (9.6.21)
Type "help" for help.
postgres=# select version();
version
-----------------------------------------------------------------------------------------------------------
PostgreSQL 9.6.21 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit
(1 row)
postgres=# 二处理和分析步骤
1 查看现有SQL执行计划
fdp_image_center=> explain analyze SELECT id,receive_source,receive_data,receive_api,receive_dubbo_bean,receive_dubbo_method,deal_status,del_status,failure_code,
failure_reason,remark,create_ts,create_user_id,update_ts,update_user_id FROM t_fdp_mgc_api_receive_log WHERE id='1G2AFM2704EG6815C0C000003E3F1006';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------
Seq Scan on t_fdp_mgc_api_receive_log (cost=0.00..672426.96 rows=1 width=867) (actual time=1844.985..4114.065 rows=1 loops=1)
Filter: (id = '1G2AFM2704EG6815C0C000003E3F1006'::bpchar)
Rows Removed by Filter: 3889740
Planning time: 0.126 ms
Execution time: 4114.110 ms
(5 rows)
Time: 4115.282 ms
fdp_image_center=>2 查看表结构
fdp_image_center=> \d t_fdp_mgc_api_receive_log
Table "public.t_fdp_mgc_api_receive_log"
Column | Type | Modifiers
----------------------+--------------------------------+---------------------
id | character(32) | not null
receive_source | character varying | not null
receive_data | text |
receive_api | text |
receive_dubbo_bean | character varying |
receive_dubbo_method | character varying |
deal_status | character(1) | default '0'::bpchar
del_status | character(1) | default '0'::bpchar
failure_code | character varying |
failure_reason | character varying |
remark | character varying |
create_ts | timestamp(6) without time zone |
create_user_id | character(32) |
update_ts | timestamp(6) without time zone |
update_user_id | character(32) |
fdp_image_center=> \dt+ t_fdp_mgc_api_receive_log
List of relations
Schema | Name | Type | Owner | Size | Description
--------+---------------------------+-------+------------------+---------+-----------------------------
public | t_fdp_mgc_api_receive_log | table | fdp_image_center | 4899 MB | 影像中心_接口数据接收日志表
(1 row)
fdp_image_center=> select count(*) from t_fdp_mgc_api_receive_log;
count
---------
3889746
(1 row)
Time: 2578.878 ms
fdp_image_center=>目标表上没有任何索引,数据量3889746,表大小4899 MB。
3 添加主键index
fdp_image_center=> alter table t_fdp_mgc_api_receive_log add primary key(id);
ALTER TABLE
fdp_image_center=> \d t_fdp_mgc_api_receive_log
Table "public.t_fdp_mgc_api_receive_log"
Column | Type | Modifiers
----------------------+--------------------------------+---------------------
id | character(32) | not null
receive_source | character varying | not null
receive_data | text |
receive_api | text |
receive_dubbo_bean | character varying |
receive_dubbo_method | character varying |
deal_status | character(1) | default '0'::bpchar
del_status | character(1) | default '0'::bpchar
failure_code | character varying |
failure_reason | character varying |
remark | character varying |
create_ts | timestamp(6) without time zone |
create_user_id | character(32) |
update_ts | timestamp(6) without time zone |
update_user_id | character(32) |
Indexes:
"t_fdp_mgc_api_receive_log_pkey" PRIMARY KEY, btree (id)
fdp_image_center=> explain analyze SELECT id,receive_source,receive_data,receive_api,receive_dubbo_bean,receive_dubbo_method,deal_status,del_status,failure_code,
failure_reason,remark,create_ts,create_user_id,update_ts,update_user_id FROM t_fdp_mgc_api_receive_log WHERE id='1G2AFM2704EG6815C0C000003E3F1006';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------
Seq Scan on t_fdp_mgc_api_receive_log (cost=0.00..672426.96 rows=1 width=867) (actual time=1844.985..4114.065 rows=1 loops=1)
Filter: (id = '1G2AFM2704EG6815C0C000003E3F1006'::bpchar)
Rows Removed by Filter: 3889740
Planning time: 0.126 ms
Execution time: 4114.110 ms
(5 rows)
Time: 4115.282 ms
fdp_image_center=>添加主键index之后,发现SQL依然走的是全表扫描,主键index不生效。
4 收集表统计信息
fdp_image_center=> analyze verbose t_fdp_mgc_api_receive_log;
INFO: analyzing "public.t_fdp_mgc_api_receive_log"
INFO: "t_fdp_mgc_api_receive_log": scanned 30000 of 623803 pages, containing 187804 live rows and 2128 dead rows; 30000 rows in sample, 3905090 estimated total rows
ANALYZE
Time: 2950.674 ms
fdp_image_center=> explain analyze SELECT id FROM t_fdp_mgc_api_receive_log WHERE id='1G2AFM2704EG6815C0C000003E3F1006';
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------
Seq Scan on t_fdp_mgc_api_receive_log (cost=0.00..672616.62 rows=1 width=33) (actual time=3195.233..4508.299 rows=1 loops=1)
Filter: (id = '1G2AFM2704EG6815C0C000003E3F1006'::bpchar)
Rows Removed by Filter: 3889762
Planning time: 0.357 ms
Execution time: 4508.325 ms
(5 rows)
Time: 4509.674 ms
fdp_image_center=> 收集完统计信息之后,执行计划依然是全表扫描。
到这里,内心感到纳闷儿,咋回事儿,主键索引不生效,更新表统计信息之后,依然不奏效。
5 重建主键约束
fdp_image_center=> alter table t_fdp_mgc_api_receive_log drop constraint t_fdp_mgc_api_receive_log_pkey ;
ALTER TABLE
Time: 1381.749 ms
fdp_image_center=> \d t_fdp_mgc_api_receive_log
Table "public.t_fdp_mgc_api_receive_log"
Column | Type | Modifiers
----------------------+--------------------------------+---------------------
id | character(32) | not null
receive_source | character varying | not null
receive_data | text |
receive_api | text |
receive_dubbo_bean | character varying |
receive_dubbo_method | character varying |
deal_status | character(1) | default '0'::bpchar
del_status | character(1) | default '0'::bpchar
failure_code | character varying |
failure_reason | character varying |
remark | character varying |
create_ts | timestamp(6) without time zone |
create_user_id | character(32) |
update_ts | timestamp(6) without time zone |
update_user_id | character(32) |
fdp_image_center=> alter table t_fdp_mgc_api_receive_log add constraint unique_id primary key(id);
ALTER TABLE
Time: 36688.809 ms
fdp_image_center=> \d t_fdp_mgc_api_receive_log
Table "public.t_fdp_mgc_api_receive_log"
Column | Type | Modifiers
----------------------+--------------------------------+---------------------
id | character(32) | not null
receive_source | character varying | not null
receive_data | text |
receive_api | text |
receive_dubbo_bean | character varying |
receive_dubbo_method | character varying |
deal_status | character(1) | default '0'::bpchar
del_status | character(1) | default '0'::bpchar
failure_code | character varying |
failure_reason | character varying |
remark | character varying |
create_ts | timestamp(6) without time zone |
create_user_id | character(32) |
update_ts | timestamp(6) without time zone |
update_user_id | character(32) |
Indexes:
"unique_id" PRIMARY KEY, btree (id)
fdp_image_center=> vacuum freeze verbose ANALYZE t_fdp_mgc_api_receive_log;
INFO: vacuuming "public.t_fdp_mgc_api_receive_log"
INFO: scanned index "unique_id" to remove 43239 row versions
DETAIL: CPU 0.09s/0.26u sec elapsed 0.35 sec
INFO: "t_fdp_mgc_api_receive_log": removed 43239 row versions in 43234 pages
DETAIL: CPU 1.11s/0.54u sec elapsed 8.53 sec
INFO: index "unique_id" now contains 3890163 row versions in 28045 pages
DETAIL: 0 index row versions were removed.
0 index pages have been deleted, 0 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO: "t_fdp_mgc_api_receive_log": found 301 removable, 3138172 nonremovable row versions in 527811 out of 623803 pages
DETAIL: 383 dead row versions cannot be removed yet.
There were 220507 unused item pointers.
Skipped 1 page due to buffer pins.
0 pages are entirely empty.
CPU 9.39s/5.67u sec elapsed 62.76 sec.
INFO: vacuuming "pg_toast.pg_toast_51870"
INFO: scanned index "pg_toast_51870_index" to remove 23 row versions
DETAIL: CPU 0.00s/0.00u sec elapsed 0.57 sec
INFO: "pg_toast_51870": removed 23 row versions in 10 pages
DETAIL: CPU 0.00s/0.00u sec elapsed 0.00 sec
INFO: index "pg_toast_51870_index" now contains 14774 row versions in 43 pages
DETAIL: 23 index row versions were removed.
0 index pages have been deleted, 0 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO: "pg_toast_51870": found 7 removable, 14774 nonremovable row versions in 3008 out of 3008 pages
DETAIL: 0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
Skipped 0 pages due to buffer pins.
0 pages are entirely empty.
CPU 0.12s/0.05u sec elapsed 7.12 sec.
INFO: analyzing "public.t_fdp_mgc_api_receive_log"
INFO: "t_fdp_mgc_api_receive_log": scanned 30000 of 623803 pages, containing 187359 live rows and 14 dead rows; 30000 rows in sample, 3895837 estimated total rows
VACUUM
Time: 73112.829 ms
fdp_image_center=> explain analyze SELECT id,receive_source,receive_data,receive_api,receive_dubbo_bean,receive_dubbo_method,deal_status,del_status,failure_code,
failure_reason,remark,create_ts,create_user_id,update_ts,update_user_id FROM t_fdp_mgc_api_receive_log WHERE id='1G2AFM2704EG6815C0C000003E3F1006';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------
Seq Scan on t_fdp_mgc_api_receive_log (cost=0.00..672500.96 rows=1 width=869) (actual time=2505.320..4352.022 rows=1 loops=1)
Filter: (id = '1G2AFM2704EG6815C0C000003E3F1006'::bpchar)
Rows Removed by Filter: 3889888
Planning time: 0.541 ms
Execution time: 4352.068 ms
(5 rows)
Time: 4353.649 ms
fdp_image_center=> 此时的我,内心开始凌乱….一通操作,开始怀疑主键约束是不是真的创建了index?重建主键约束,还是不生效….
6 手工添加btree index
fdp_image_center=> create index CONCURRENTLY idx_fdp_mgc_api_receive_log_id on t_fdp_mgc_api_receive_log(id);
CREATE INDEX
Time: 39576.585 ms
fdp_image_center=> \d t_fdp_mgc_api_receive_log
Table "public.t_fdp_mgc_api_receive_log"
Column | Type | Modifiers
----------------------+--------------------------------+---------------------
id | character(32) | not null
receive_source | character varying | not null
receive_data | text |
receive_api | text |
receive_dubbo_bean | character varying |
receive_dubbo_method | character varying |
deal_status | character(1) | default '0'::bpchar
del_status | character(1) | default '0'::bpchar
failure_code | character varying |
failure_reason | character varying |
remark | character varying |
create_ts | timestamp(6) without time zone |
create_user_id | character(32) |
update_ts | timestamp(6) without time zone |
update_user_id | character(32) |
Indexes:
"unique_id" PRIMARY KEY, btree (id)
"idx_fdp_mgc_api_receive_log_id" btree (id)
fdp_image_center=> explain analyze SELECT id FROM t_fdp_mgc_api_receive_log WHERE id='1G2AFM2704EG6815C0C000003E3F1006';
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------
Index Only Scan using idx_fdp_mgc_api_receive_log_id on t_fdp_mgc_api_receive_log (cost=0.56..8.57 rows=1 width=33) (actual time=0.070..0.071 rows=1 loops=1)
Index Cond: (id = '1G2AFM2704EG6815C0C000003E3F1006'::bpchar)
Heap Fetches: 0
Planning time: 0.297 ms
Execution time: 0.099 ms
(5 rows)
Time: 1.064 ms
fdp_image_center=>啥情况?通过添加主键约束,进而隐式创建的主键index不生效,反而我手工创建的一个普通btree index却生效了。
7 复盘index信息
fdp_image_center=> select tablename,indexname,indexdef from pg_indexes where tablename='t_fdp_mgc_api_receive_log';
tablename | indexname | indexdef
---------------------------+--------------------------------+--------------------------------------------------------------------------------------------------
t_fdp_mgc_api_receive_log | unique_id | CREATE UNIQUE INDEX unique_id ON public.t_fdp_mgc_api_receive_log USING btree (id)
t_fdp_mgc_api_receive_log | idx_fdp_mgc_api_receive_log_id | CREATE INDEX idx_fdp_mgc_api_receive_log_id ON public.t_fdp_mgc_api_receive_log USING btree (id)
(2 rows)
Time: 15.095 ms
fdp_image_center=> 8 想重现该现象
把该表导出来,然后导入到另外一个库上,想看看该情况是否会重现?
导出表:
pg_dump -h localhost -p 5432 -d fdp_image_center -U fdp_image_center -t t_fdp_mgc_api_receive_log -f t_fdp_mgc_api_receive_log.dmp
删除该表的dump文件里的已有的2个index:vi t_fdp_mgc_api_receive_log.dmp 删掉index信息,保存退出。
新库导入表:
bill_fmt=> \i t_fdp_mgc_api_receive_log.dmp
CREATE TABLE
psql:t_fdp_mgc_api_receive_log.dmp:25: ERROR: must be member of role "fdp_image_center"
COMMENT
COMMENT
COMMENT
COMMENT
COMMENT
COMMENT
COMMENT
COMMENT
COMMENT
COMMENT
COMMENT
COMMENT
COMMENT
COMMENT
COMMENT
COMMENT
COPY 3915872
bill_fmt=> \d t_fdp_mgc_api_receive_log
Table "public.t_fdp_mgc_api_receive_log"
Column | Type | Modifiers
----------------------+--------------------------------+---------------------
id | character(32) | not null
receive_source | character varying | not null
receive_data | text |
receive_api | text |
receive_dubbo_bean | character varying |
receive_dubbo_method | character varying |
deal_status | character(1) | default '0'::bpchar
del_status | character(1) | default '0'::bpchar
failure_code | character varying |
failure_reason | character varying |
remark | character varying |
create_ts | timestamp(6) without time zone |
create_user_id | character(32) |
update_ts | timestamp(6) without time zone |
update_user_id | character(32) |
bill_fmt=> \dt+ t_fdp_mgc_api_receive_log
List of relations
Schema | Name | Type | Owner | Size | Description
--------+---------------------------+-------+----------+---------+-----------------------------
public | t_fdp_mgc_api_receive_log | table | bill_fmt | 3396 MB | 影像中心_接口数据接收日志表
(1 row)
bill_fmt=>查看执行计划:
bill_fmt=> explain analyze SELECT id,receive_source,receive_data,receive_api,receive_dubbo_bean,receive_dubbo_method,deal_status,del_status,failure_code,
failure_reason,remark,create_ts,create_user_id,update_ts,update_user_id FROM t_fdp_mgc_api_receive_log WHERE id='1G2AFM2704EG6815C0C000003E3F1006';
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------
Seq Scan on t_fdp_mgc_api_receive_log (cost=0.00..480472.40 rows=1 width=869) (actual time=881.723..6629.848 rows=1 loops=1)
Filter: (id = '1G2AFM2704EG6815C0C000003E3F1006'::bpchar)
Rows Removed by Filter: 3915871
Planning time: 0.095 ms
Execution time: 6629.884 ms
(5 rows)
bill_fmt=> 添加主键约束:
bill_fmt=> alter table t_fdp_mgc_api_receive_log add primary key(id);
ALTER TABLE
bill_fmt=> \d t_fdp_mgc_api_receive_log
Table "public.t_fdp_mgc_api_receive_log"
Column | Type | Modifiers
----------------------+--------------------------------+---------------------
id | character(32) | not null
receive_source | character varying | not null
receive_data | text |
receive_api | text |
receive_dubbo_bean | character varying |
receive_dubbo_method | character varying |
deal_status | character(1) | default '0'::bpchar
del_status | character(1) | default '0'::bpchar
failure_code | character varying |
failure_reason | character varying |
remark | character varying |
create_ts | timestamp(6) without time zone |
create_user_id | character(32) |
update_ts | timestamp(6) without time zone |
update_user_id | character(32) |
Indexes:
"t_fdp_mgc_api_receive_log_pkey" PRIMARY KEY, btree (id)
bill_fmt=> explain analyze SELECT id,receive_source,receive_data,receive_api,receive_dubbo_bean,receive_dubbo_method,deal_status,del_status,failure_code,
failure_reason,remark,create_ts,create_user_id,update_ts,update_user_id FROM t_fdp_mgc_api_receive_log WHERE id='1G2AFM2704EG6815C0C000003E3F1006';
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using t_fdp_mgc_api_receive_log_pkey on t_fdp_mgc_api_receive_log (cost=0.56..8.57 rows=1 width=869) (actual time=0.167..0.168 rows=1 loops=1)
Index Cond: (id = '1G2AFM2704EG6815C0C000003E3F1006'::bpchar)
Planning time: 0.370 ms
Execution time: 0.206 ms
(4 rows)
bill_fmt=> 这时,想重现该现象,发现添加主键约束之后,SQL执行计划立即改善。
手工创建btree index:
bill_fmt=> create index CONCURRENTLY idx_t_fdp_mgc_api_receive_log_id on t_fdp_mgc_api_receive_log(id);
CREATE INDEX
bill_fmt=> \d t_fdp_mgc_api_receive_log
Table "public.t_fdp_mgc_api_receive_log"
Column | Type | Modifiers
----------------------+--------------------------------+---------------------
id | character(32) | not null
receive_source | character varying | not null
receive_data | text |
receive_api | text |
receive_dubbo_bean | character varying |
receive_dubbo_method | character varying |
deal_status | character(1) | default '0'::bpchar
del_status | character(1) | default '0'::bpchar
failure_code | character varying |
failure_reason | character varying |
remark | character varying |
create_ts | timestamp(6) without time zone |
create_user_id | character(32) |
update_ts | timestamp(6) without time zone |
update_user_id | character(32) |
Indexes:
"t_fdp_mgc_api_receive_log_pkey" PRIMARY KEY, btree (id)
"idx_t_fdp_mgc_api_receive_log_id" btree (id)
bill_fmt=> explain analyze SELECT id,receive_source,receive_data,receive_api,receive_dubbo_bean,receive_dubbo_method,deal_status,del_status,failure_code,
failure_reason,remark,create_ts,create_user_id,update_ts,update_user_id FROM t_fdp_mgc_api_receive_log WHERE id='1G2AFM2704EG6815C0C000003E3F1006';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using idx_t_fdp_mgc_api_receive_log_id on t_fdp_mgc_api_receive_log (cost=0.56..8.57 rows=1 width=869) (actual time=0.050..0.051 rows=1 loops=1)
Index Cond: (id = '1G2AFM2704EG6815C0C000003E3F1006'::bpchar)
Planning time: 0.416 ms
Execution time: 0.105 ms
(4 rows)
bill_fmt=>再看此时的执行计划,就更滑稽了,原有的主键index不走,PostgreSQL的优化器反而用了新建的btree index!
继续分析:
bill_fmt=> drop index idx_t_fdp_mgc_api_receive_log_id;
DROP INDEX
bill_fmt=> explain analyze SELECT id,receive_source,receive_data,receive_api,receive_dubbo_bean,receive_dubbo_method,deal_status,del_status,failure_code,
failure_reason,remark,create_ts,create_user_id,update_ts,update_user_id FROM t_fdp_mgc_api_receive_log WHERE id='1G2AFM2704EG6815C0C000003E3F1006';
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using t_fdp_mgc_api_receive_log_pkey on t_fdp_mgc_api_receive_log (cost=0.56..8.57 rows=1 width=869) (actual time=0.048..0.050 rows=1 loops=1)
Index Cond: (id = '1G2AFM2704EG6815C0C000003E3F1006'::bpchar)
Planning time: 0.226 ms
Execution time: 0.090 ms
(4 rows)
bill_fmt=> 优化器,你也不傻呀。还是用回了主键index。
扫尾工作:
连回到原来的数据库,删掉btree index之后,优化器又识别了主键index,并且生效了。
postgres=# \c fdp_image_center fdp_image_center
You are now connected to database "fdp_image_center" as user "fdp_image_center".
fdp_image_center=> explain analyze SELECT id,receive_source,receive_data,receive_api,receive_dubbo_bean,receive_dubbo_method,deal_status,del_status,failure_code,
failure_reason,remark,create_ts,create_user_id,update_ts,update_user_id FROM t_fdp_mgc_api_receive_log WHERE id='1G2AFM2704EG6815C0C000003E3F1006';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using idx_fdp_mgc_api_receive_log_id on t_fdp_mgc_api_receive_log (cost=0.56..8.57 rows=1 width=869) (actual time=16.280..16.282 rows=1 loops=1)
Index Cond: (id = '1G2AFM2704EG6815C0C000003E3F1006'::bpchar)
Planning time: 83.287 ms
Execution time: 16.397 ms
(4 rows)
fdp_image_center=> \d t_fdp_mgc_api_receive_log
Table "public.t_fdp_mgc_api_receive_log"
Column | Type | Modifiers
----------------------+--------------------------------+---------------------
id | character(32) | not null
receive_source | character varying | not null
receive_data | text |
receive_api | text |
receive_dubbo_bean | character varying |
receive_dubbo_method | character varying |
deal_status | character(1) | default '0'::bpchar
del_status | character(1) | default '0'::bpchar
failure_code | character varying |
failure_reason | character varying |
remark | character varying |
create_ts | timestamp(6) without time zone |
create_user_id | character(32) |
update_ts | timestamp(6) without time zone |
update_user_id | character(32) |
Indexes:
"unique_id" PRIMARY KEY, btree (id)
"idx_fdp_mgc_api_receive_log_id" btree (id)
fdp_image_center=> drop index idx_fdp_mgc_api_receive_log_id;
DROP INDEX
fdp_image_center=> explain analyze SELECT id,receive_source,receive_data,receive_api,receive_dubbo_bean,receive_dubbo_method,deal_status,del_status,failure_code,
failure_reason,remark,create_ts,create_user_id,update_ts,update_user_id FROM t_fdp_mgc_api_receive_log WHERE id='1G2AFM2704EG6815C0C000003E3F1006';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------
Index Scan using unique_id on t_fdp_mgc_api_receive_log (cost=0.56..8.57 rows=1 width=869) (actual time=21.814..21.816 rows=1 loops=1)
Index Cond: (id = '1G2AFM2704EG6815C0C000003E3F1006'::bpchar)
Planning time: 0.230 ms
Execution time: 21.852 ms
(4 rows)
fdp_image_center=> explain analyze SELECT id,receive_source,receive_data,receive_api,receive_dubbo_bean,receive_dubbo_method,deal_status,del_status,failure_code,
failure_reason,remark,create_ts,create_user_id,update_ts,update_user_id FROM t_fdp_mgc_api_receive_log WHERE id='1G2AFM2704EG6815C0C000003E3F1006';
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
Index Scan using unique_id on t_fdp_mgc_api_receive_log (cost=0.56..8.57 rows=1 width=869) (actual time=0.056..0.057 rows=1 loops=1)
Index Cond: (id = '1G2AFM2704EG6815C0C000003E3F1006'::bpchar)
Planning time: 0.135 ms
Execution time: 0.095 ms
(4 rows)
fdp_image_center=> 三小结
1 PostgreSQL数据库给表添加主键约束时,会自动在该表上创建主键index。这一点儿跟Oracle数据库不同,Oracle里约束是约束,index是index;
2 PostgreSQL数据库给表添加了主键约束,进而隐式的创建了主键index,可是,该index不生效,更新了表统计信息之后,主键index依然不生效;不得已手工添加了btree index反而生效,纳闷儿?
3 同一个数据库服务器,换1个数据库,重现该现象时,一旦添加主键约束,优化器立即识别了主键index,并且生效了,更纳闷儿?
4 暂且把这个问题现象记录下来,留作以后慢慢再复盘吧。我自己都解释不了,说不定以后复盘时会有更新的收获和认知。


