经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » PostgreSQL » 查看文章
PostgreSQL 务实应用(三/5)分表复制
来源:cnblogs  作者:三人行工作室  时间:2019/5/17 8:43:24  对本文有异议

问题的提出

在项目中,有些表的记录增长非常快,记录数过大时会使得查询变得困难,导致整个数据库处理性能下降。此时,我们会考虑按一定的规则进行分表存储。

常用的分表方式是按时间周期,如每月一张,每天一张等。当每月或每天首条记录到达时,根据表结构创建该周期为后缀的表进行存储。

相关考虑

这其中主要考虑两个问题:

(1)如何复制表

采用分表机制,通常会建立一个模板表。所谓模板表,是只定义结构不存储数据的,也可称之为类表,而分表,通常会以增加后缀的方式命名,如 log_201901,分表实际存储数据,可称之为实例表。

表存在关联、键、索引、约束等,这让表的复制听起来比较繁琐,即便通过元数据得到这些信息,还需要自己考虑如索引的命名冲突等问题。而 PostgreSQL 为我们提供了极其便捷的方式。

  1. CREATE TABLE [IF NOT EXISTS] 实例表 (LIKE 模板表 [INCLUDING ALL]);

其中 [ ] 内表示可选项,INCLUDING 除了 ALL 还要其它细分的选项,具体可参考帮助文档。

(2)数据存储的逻辑过程

首先得知道表存不存在,不存在则要创建,然后执行数据操作语句。

由于表名是动态的,在应用系统中可以先取得表名形成 SQL 语句再执行,在数据库存储过程中则可以使用 EXECUTE 执行动态SQL语句。

分表实例

下边,本文以日志记录表为例来完整地实践分表处理过程。

功能描述:日志数量大,当前日志查询频繁,历史日志需要全部保存。要求每天一个分表,日志主键要求全局保持唯一性(即多个分表间不重复),日志到达自动根据当前的时间进行分表存储。

首先创建日志模板表,命名为 log_template,并为其建立相关索引,主键序列。

  1. -- 创建模板表,log_id 主键,log_at 日志时间, log_content 日志内容
  2. CREATE TABLE log_template (log_id bigint PRIMARY KEY,
  3. log_at timestamp, log_content varchar(1000));
  4. -- 对日志时间索引
  5. CREATE INDEX idx_log_at on log_template (log_at);
  6. -- 用于主键的序列(各分表使用同一序列)
  7. CREATE SEQUENCE seq_log_id;

我们通过一个过程来完成日志的自动分表存储。

  1. CREATE OR REPLACE FUNCTION func_log(v_conent varchar) RETURNS bool LANGUAGE 'plpgsql'
  2. AS $$
  3. DECLARE
  4. lv_log_at timestamp := current_timestamp;
  5. lv_suffix_tname varchar; -- 带后缀的分表名
  6. lv_dsql text; -- 动态SQL
  7. BEGIN
  8. -- 根据时间得到应使用的分表名称
  9. lv_suffix_tname := 'log_' || to_char(lv_log_at, 'YYYYMMDD');
  10. -- 判断是否存在,不存在时复制模板创建分表
  11. lv_dsql := 'CREATE TABLE IF NOT EXISTS ' || lv_suffix_tname || ' (LIKE log_template INCLUDING ALL)';
  12. EXECUTE lv_dsql;
  13. -- 将数据保存至分表
  14. lv_dsql := 'INSERT INTO ' || lv_suffix_tname || '(log_id, log_at, log_content) VALUES($1, $2, $3)';
  15. EXECUTE lv_dsql USING nextval('seq_log_id'), lv_log_at, v_conent;
  16. RETURN true;
  17. END $$;

执行以下语句来看看预期的结果。

  1. SELECT func_log('hello, the first log!');
  2. SELECT func_log('toady is a nice day!');
  3. SELECT func_log('每天都有新的开始,不再担心爆表!');

结束语

分表能够避免单表记录过于庞大,提高查询性能。但同时,分表也会给部分查询或数据处理带有复杂性,因此是否分表应该根据业务需要来,同时应尽早规划,后期更改相对繁琐。

在 MySQL 中也有类似的 CREATE TABLE LIKE 语法,我想都是应运而生,简单就是美。

原文链接:http://www.cnblogs.com/timeddd/p/10874007.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号