分表概述

数据库分表,就是把一张表分成多张表,物理上虽然分开了,逻辑上彼此仍有联系。

分表有两种方式:水平分表,即按列分开;垂直分表,即按行分开

优势

1. 查询速度大幅提升

2. 删除数据速度更快

3. 可以将使用率低的数据通过表空间技术转移到低成本的存储介质上

场景

官方建议:当数据表大小超过数据库服务器内存时应该使用分表。

两种分表方式大致相同,下面以垂直分表为例进行介绍。

垂直分表

基本过程

1. 创建父表

2. 创建子表,子表必须继承父表,最好不要新加字段  【加了以后如何,没试过】

  // 可以给每个子表创建索引

3. 定义一个规则(rule) 或者触发器(trigger),把对父表的写入重定向到对应的分表

创建父表

父表无数据,无约束,无索引

CREATE TABLE tbl_partition
(
date_key date,
hour_key smallint,
client_key integer,
item_key integer,
account integer,
expense numeric
);

创建分表

分表必须继承父表

CREATE TABLE tbl_partition_2016_01() inherits (tbl_partition);
CREATE TABLE tbl_partition_2016_02() inherits (tbl_partition);
CREATE TABLE tbl_partition_2016_03() inherits (tbl_partition);

分表需要添加限制,这些限制决定了每张表允许保存的数据范围,每张表的限制范围不能有重叠。

ALTER TABLE tbl_partition_2016_01
ADD CONSTRAINT tbl_partition_2016_01_check_date_key
CHECK (date_Key >= '2016-01-01'::date AND date_Key < '2016-02-01'::date);
ALTER TABLE tbl_partition_2016_02
ADD CONSTRAINT tbl_partition_2016_02_check_date_key
CHECK (date_Key >= '2016-02-01'::date AND date_Key < '2016-03-01'::date);
ALTER TABLE tbl_partition_2016_03
ADD CONSTRAINT tbl_partition_2016_03_check_date_key
CHECK (date_Key >= '2016-03-01'::date AND date_Key < '2016-04-01'::date);

也可以建表和限制写在一起

create table t_sys_log_y2016m09
(CHECK (operation_time >= DATE '2016-09-01' AND operation_time< DATE '2016-10-01'))
INHERITS (t_sys_log_main);

给分表添加索引

CREATE INDEX tbl_partition_date_key_2016_01
ON tbl_partition_2016_01 (date_key,client_key);
CREATE INDEX tbl_partition_date_key_2016_02
ON tbl_partition_2016_02 (date_key,client_key);
CREATE INDEX tbl_partition_date_key_2016_03
ON tbl_partition_2016_03 (date_key,client_key);

创建触发器

表建立完成后,就是写入的工作,如何将数据自动写入对应的分表呢?两种方法,分别是规则(rule)和触发器(trigger),相比 trigger,rule 开销更大,这里使用触发器。

trigger 通常会结合自定义函数来实现分区插入:Function 负责根据条件选择插入,trigger 负责自动调用 Function

首先定义 Function

CREATE OR REPLACE FUNCTION tbl_partition_trigger()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.date_key >= DATE '2016-01-01' AND NEW.date_Key < DATE '2016-02-01'
THEN
INSERT INTO tbl_partition_2016_01 VALUES (NEW.*);
ELSIF NEW.date_key >= DATE '2016-02-01' AND NEW.date_Key < DATE '2016-03-01'
THEN
INSERT INTO tbl_partition_2016_02 VALUES (NEW.*);
ELSIF NEW.date_key >= DATE '2016-03-01' AND NEW.date_Key < DATE '2016-04-01'
THEN
INSERT INTO tbl_partition_2016_03 VALUES (NEW.*);
END IF;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;

对父表创建触发器

CREATE TRIGGER insert_tbl_partition_trigger
BEFORE INSERT ON tbl_partition
FOR EACH ROW EXECUTE PROCEDURE tbl_partition_trigger();

至此分表成功

性能对比

为了对比分表与不分表的性能,我创建了一个全表。

CREATE TABLE tbl_partition_all
(
date_key date,
hour_key smallint,
client_key integer,
item_key integer,
account integer,
expense numeric
);

把数据先全部写到全表后,迁移到分表

INSERT INTO tbl_partition SELECT * FROM tbl_partition_all;

全表9w条数据,分表每个3w条,测试如下

1. 分表 - 查询单个分表内的数据

EXPLAIN  ANALYZE
select count(account) ,client_key from tbl_partition v
where v.date_key >='2016-03-02' and v.date_key <='2016-03-07' group by client_key ;

3月份的数据在一个表内,耗时约 18s

全表查同样的数据

EXPLAIN  ANALYZE
select count(account) ,client_key from tbl_partition_all v
where v.date_key >='2016-03-02' and v.date_key <='2016-03-07' group by client_key ;

耗时约 30s

2. 分表 - 查询跨分表的数据

EXPLAIN  ANALYZE
select count(account) ,client_key from tbl_partition v
where v.date_key >='2016-01-02' and v.date_key <='2016-03-07' group by client_key ;

跨3个表,耗时约 65s

全表查同样的数据

EXPLAIN  ANALYZE
select count(account) ,client_key from tbl_partition_all v
where v.date_key >='2016-01-02' and v.date_key <='2016-03-07' group by client_key ;

耗时约 87s

3. 有同事问为什么不直接分呢?不继承单纯按数据建多个表

对此我也进行了测试,单独建立3个表,分别存放之前每个分表的数据,分别建立索引,然后查询同样的数据

EXPLAIN  ANALYZE
select count(account) ,client_key from test1 v
where v.date_key >='2016-01-02' and v.date_key <='2016-01-28' group by client_key
union
select count(account) ,client_key from test2 v
where v.date_key >='2016-02-01' and v.date_key <='2016-02-28' group by client_key
union
select count(account) ,client_key from test3 v
where v.date_key >='2016-03-01' and v.date_key <='2016-03-07' group by client_key ;

耗时约 180s,效率更低

总结:分表效率很高,优于全表和多个单表,我这里只是用了少量的数据,性能并没有提升很大,如果数据量很大,性能应该提升明显。

分表其他操作

删除继承关系

ALTER TABLE tbl_partition_2016_01 NO INHERIT tbl_partition;

添加继承关系

ALTER TABLE test1 INHERIT tbl_partition;

参考资料:

https://www.cnblogs.com/winkey4986/p/6824747.html

https://www.jb51.net/article/97937.htm

https://blog.csdn.net/imthemostshuaiin626/article/details/77318911

https://hacpai.com/article/1536655962119

PostgreSQL-优化之分表的更多相关文章

  1. MYSQL性能优化--分库分表

    1.分库分表 1>纵向分表 将本来可以在同一个表的内容,人为划分为多个表.(所谓的本来,是指按照关系型数据库的第三范式要求,是应该在同一个表的.) 分表理由:根据数据的活跃度进行分离,(因为不同 ...

  2. Postgresql分表与优化

    --1.创建主表 CREATE TABLE tbl_partition ( date_key date, hour_key smallint, client_key integer, item_key ...

  3. WebGIS项目中利用mysql控制点库进行千万条数据坐标转换时的分表分区优化方案

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1. 背景 项目中有1000万条历史案卷,为某地方坐标系数据,我们的真实 ...

  4. Mysql性能优化三(分表、增量备份、还原)

    接上篇Mysql性能优化二 对表进行水平划分 如果一个表的记录数太多了,比如上千万条,而且需要经常检索,那么我们就有必要化整为零了.如果我拆成100个表,那么每个表只有10万条记录.当然这需要数据在逻 ...

  5. C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本 - 大数据支持分表优化

    公司的短信平台,数据量越来越大了,需要对数据进行一些优化,下面是拆分后的数据库量参考. 新开发的软件模块,必须支持分表,拆表的功能一个数据表里,不适合保存1000万以上的记录新开发的业务模块,能分表的 ...

  6. mysql中的优化, 简单的说了一下垂直分表, 水平分表(有几种模运算),读写分离.

    一.mysql中的优化 where语句的优化 1.尽量避免在 where 子句中对字段进行表达式操作select id from uinfo_jifen where jifen/60 > 100 ...

  7. MYSQL性能优化分享(分库分表)

    1.分库分表 很明显,一个主表(也就是很重要的表,例如用户表)无限制的增长势必严重影响性能,分库与分表是一个很不错的解决途径,也就是性能优化途径,现在的案例是我们有一个1000多万条记录的用户表mem ...

  8. Sql的分库分表,及优化

    对Sql细节优化 在sql查询中为了提高查询效率,我们常常会采取一些措施对查询语句进行sql优化,下面总结的一些方法,有需要的可以参考参考. 首先给大家介绍一下分库分表 分库分表 分库 垂直分库 业务 ...

  9. Mysql MyISAM与InnoDB 表锁行锁以及分库分表优化

    一. 两种存储引擎:MyISAM与InnoDB 区别与作用 1. count运算上的区别: 因为MyISAM缓存有表meta-data(行数等),因此在做COUNT(*)时对于一个结构很好的查询是不需 ...

  10. MySQL优化(一):MySQL分库分表

    一.分库分表种类 1.垂直拆分 在考虑数据拆分的时候,一般情况下,应该先考虑垂直拆分.垂直可以理解为分出来的库表结构是互相独立各不相同的. - 如果有多个业务,每个业务直接关联性不大,那么就可以把每个 ...

随机推荐

  1. TTTTTTTTTTTT Codeforces Round #353 (Div. 2) D 平衡二叉树的set模拟 没有很懂

    题意:给你n个数字,第一个点作为根节点,然后每次插入一个节点,构建一棵平衡二叉树,并输出插入节点后该节点的父节点的值 #include <iostream> #include <cs ...

  2. 5.JavaBean

    JavaBean JSP开发初期HTML,css,java代码混杂在一起,给程序的调试和维护带来很大困难.将与HTML分离并将对象和逻辑java代码封装成类就是一个JavaBean组件. 1.Java ...

  3. 上一个树形菜单的改进,增添了数据绑定功能而非仅仅的jq特效

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...

  4. mybatis逆向工程的text类型的一个小坑

    数据库如果配有text的数据类型的 mybatis生成逆向工程的时候会单独将text提取出来 ByExampleWithBLOBs 会生成上面后缀的查询和修改的语句 因此查询起来会产生没有必要的麻烦, ...

  5. C++入门经典-例3.7-用条件运算符判断数的奇偶性

    1:条件运算符是一个三目运算符,能像判断语句一样完成判断.例如: max=(iA>iB) ? iA:iB; 意思是先判断iA是否大于iB,如果是,则max取iA的值,如果不是则取iB的值. 如果 ...

  6. shiro所需的依赖

    <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring< ...

  7. LeetCode328----奇偶链表

    给定一个单链表,把所有的奇数节点和偶数节点分别排在一起.请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性. 请尝试使用原地算法完成.你的算法的空间复杂度应为 O(1),时 ...

  8. Vue可自定义tab组件

    在工作中我们常常要用到tab组件,如果有用第三方组件库的话一般都会有这个组件,但如果没有使用第三方组件库,或者想要自定义tab,那么或许这个无依赖的tab组件将会极大地节约你的开发时间.     如何 ...

  9. win10上的docker怎么设置开机不要自动启动 [问题点数:20分,结帖人xyq1986]

    次win开机都自动启动docker,感觉很耗资源,docker只是有时开发时需要用到,在docker的setting上的Start Docker Desktop when you log in取消了也 ...

  10. Android-Universal-Image-Loader的缓存处理机制与使用 LruCache 缓存图片

    讲到缓存,平时流水线上的码农一定觉得这是一个高大上的东西.看过网上各种讲缓存原理的文章,总感觉那些文章讲的就是玩具,能用吗?这次我将带你一起看过UIL这个国内外大牛都追捧的图片缓存类库的缓存处理机制. ...