创建结果表的存储过程执行时间过长解决方案
结果表不要建太多,不方便维护,所以要尽可能的考虑让多业务通用。
数据库
本文基于 PostgreSQL。
问题
若创建结果表的存储过程执行时间较长,如果先TRUNCATE,再INSERT,在INSERT期间此表将无法使用。
方案
两种方案:大概思路都是向临时表刷入数据,再将临时表更名为业务表。
方案一:先建临时表,刷入数据;删除业务表,将临时表更名为业务表。
方案二:先建业务表和临时表(临时表先删再建),向临时表刷入数据;将业务表更名为old表,将临时表更名为业务表,再将old表更名为临时表并TRUNCATE(以备下次使用)。
临时表和业务表应该使用同一个序列。
方案一具体逻辑
索引创建放在插入数据之后,因为后建索引 Insert 更快。
若想先建立索引,为了避免索引重名可以使用下面方式:
1 | execute 'CREATE INDEX IF NOT EXISTS idx_t_user_' || datetime || ' ON "t_user" ( account)'; |
步骤:
1、创建序列 t_user_seq 如果不存在。
2、删除 t_user_temp 表如果存在,创建 t_user_temp 表如果不存在,并添加表和字段注释。
3、向 t_user_temp 表插入数据,使用 t_user_seq 序列。
4、删除 t_user 表如果存在,将 t_user_temp 表重命名为 t_user。
5、创建 t_user 表索引。
存储过程:
1 | call update_t_user(); |
方案二具体逻辑
由于有规定,不允许在脚本中执行 DDL 语句,需另外提供表结构变动sql(建表、索引等),可采用此方案。
步骤:
1、清空 t_user_temp 表数据,并插入数据,使用 t_user_seq 序列。
2、将 t_user_temp 表和 t_user 表替换。
建表语句:
1 | DROP TABLE IF EXISTS t_user; |
存储过程:
1 | call update_t_user(); |
选择哪一个?
如果对表结构的修改没有严格规定,推荐方案一,因为它可以灵活修改表结构,项目上生产以后会很方便。
如果严格规定不允许脚本含有修改表结构语句,那么只能选方案二。
方案二优化
因为业务需要记录同步日志,所以新增 同步记录表 sync_record
。
1 | DROP TABLE IF EXISTS t_sync_record; |
存储过程:
1 | call update_t_user(); |
PostgreSQL时区
1 | select to_char(now(), 'yyyy-mm-dd hh24:mi:ss'); |
PostgreSQL时间
1 | -- 1、当前事务开始的时间。 |