wjo*_*zsi 8 postgresql performance index disaster-recovery postgresql-10
我使用 pg_upgrade(就地)升级了 Postgres DB 9.3.2-->10.5。我根据文档和 pg_upgrade 给出的说明做了一切。一切顺利,但后来我意识到索引没有在其中一个表中使用(也许其他表也受到影响)。
所以我ANALYZE昨天在那个桌子上开始了一个仍在运行的桌子上(超过 22 小时)......!
问题:ANALYZE执行时间这么长正常吗?
该表包含大约 30M 条记录。结构是:
CREATE TABLE public.chs_contact_history_events (
event_id bigint NOT NULL
DEFAULT nextval('chs_contact_history_events_event_id_seq'::regclass),
chs_id integer NOT NULL,
event_timestamp bigint NOT NULL,
party_id integer NOT NULL,
event integer NOT NULL,
cause integer NOT NULL,
text text COLLATE pg_catalog."default",
timestamp_offset integer,
CONSTRAINT pk_contact_history_events PRIMARY KEY (event_id)
);
ALTER TABLE public.chs_contact_history_events OWNER to c_chs;
CREATE INDEX ix_chs_contact_history_events_chsid
ON public.chs_contact_history_events USING hash (chs_id)
TABLESPACE pg_default;
CREATE INDEX ix_chs_contact_history_events_id
ON public.chs_contact_history_events USING btree (event_id)
TABLESPACE pg_default;
CREATE INDEX ix_history_events_partyid
ON public.chs_contact_history_events USING hash (party_id)
TABLESPACE pg_default;
Run Code Online (Sandbox Code Playgroud)
更新:
我运行了下面的查询以获取当前正在运行的进程并获得了更多有趣的结果:
SELECT pid, now() - pg_stat_activity.query_start AS duration, query, state
FROM pg_stat_activity
WHERE (now() - pg_stat_activity.query_start) > interval '5 minutes'
AND state = 'active';
Run Code Online (Sandbox Code Playgroud)
看来维护任务和索引表的并发重建都被冻结了!
那么下一个问题:取消这些过程是否安全?下一步该怎么做?IMO 停止所有操作并重新启动索引创建将是必要的,但我不确定。
附件 1
可能在 v9 中更正的相关错误:
9.3.7 和 9.4.2 修复哈希索引桶拆分期间可能出现的失败,如果其他进程正在同时修改索引
9.3.18 和 9.4.13 和 9.5.8 和 9.6.4 修复了 Windows 版本中共享谓词锁哈希表的低概率损坏
9.5.4 修复大型(大于shared_buffers)哈希索引的构建用于大型索引的代码路径包含一个错误,导致将不正确的哈希值插入索引,因此后续索引搜索总是失败,除了插入索引的元组在初始构建之后。
可能在 v10 中更正的相关错误:
10.2 修复在添加新的溢出页面后未能将哈希索引的元页面标记为脏,可能导致索引损坏的问题
防止由于简单哈希表的过度增长而导致内存不足故障
最后但并非最不重要的是,这让我感到担忧(因为在生产环境中升级似乎不现实):
10.6 当 BLCKSZ 小于默认值时避免散列索引的元页面溢出
修复哈希索引中丢失的页面校验和更新
附件 2
v10升级说明:
从任何以前的主要 PostgreSQL 版本进行 pg_upgrade-ing 后,必须重建哈希索引
主要的哈希索引改进使这一要求成为必要。pg_upgrade 将创建一个脚本来帮助解决这个问题。
请注意,我当然在升级时运行了该脚本。
经过几个小时的研究和检查当前情况,我想我设法解决了这个问题。(非常感谢用户 ypercube 的启发和 Erwin Brandstetter,他们同时提出了相同的解决方案。)
所以有几个层面的问题。
1.) 升级
升级 pg_upgrade 9.3.2 --> 10.5 应该分两步进行。首先在同一行(9.3.2 --> 9.3.25)然后到 10.x(在我的例子中是 10.5)
我进行了直接升级,似乎这是问题的根本原因。
2.) 哈希索引
似乎散列索引在 postgres 中出现了一些奇怪的错误,这些错误已经得到纠正,但是使用更正前版本的索引会导致错误
3.) 冻结任务
寻找运行时间不切实际的 postgres 进程确实有意义。(请参阅问题中的查询。)在我的情况下,结果证明索引的重新创建以某种方式卡住了,并且其他几个任务也被阻止了。
可以安全地取消其中的大部分,SELECT pg_cancel_backend(__pid__);其中pid是在上述查询的结果集中找到的进程 ID。所以我做到了。我什至停止了 autovacuum 进程。
4.) 内存处理
完成所有这些之后,我终于认为我可以删除和创建新索引,我面临下一个问题。大约一分钟后,所有维护查询都退出并显示错误消息:
ERROR: out of memory
DETAIL: Failed on request of size 22355968.
SQL state: 53200
Run Code Online (Sandbox Code Playgroud)
似乎内存处理在 9.3 和 10 之间发生了变化。我不得不减少配置中的 maintenance_mem 数量:
maintenance_work_mem = 64MB # min 1MB
Run Code Online (Sandbox Code Playgroud)
之前是 512MB,虽然服务器有 32GB 的 RAM,但它仍然无法使用。
5.) 重建索引
毕竟可以重新创建索引(删除旧索引并创建新索引)。使用适当的脚本会更容易,但我必须手动完成。不要忘记创建和删除索引会锁定表,因此在生产环境(如我的)中,您应该同时执行此操作。
编辑:
我也意识到在我的特定情况下使用哈希索引并不是很有意义,所以我决定在娱乐时将它们更改为 btree。
6.) 分析
重新创建索引后,有必要对受影响的表(或整个数据库)运行分析。完成上述所有操作后,即使在像我这样的大型数据库中,它也能以惊人的速度运行。
索引再次被使用,性能再次完美。所以这是我第一篇 StackExchange 帖子的圆满结局。:-)
| 归档时间: |
|
| 查看次数: |
872 次 |
| 最近记录: |