PostgreSQL-优化之分表
分表概述
数据库分表,就是把一张表分成多张表,物理上虽然分开了,逻辑上彼此仍有联系。
分表有两种方式:水平分表,即按列分开;垂直分表,即按行分开
优势
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-优化之分表的更多相关文章
- MYSQL性能优化--分库分表
1.分库分表 1>纵向分表 将本来可以在同一个表的内容,人为划分为多个表.(所谓的本来,是指按照关系型数据库的第三范式要求,是应该在同一个表的.) 分表理由:根据数据的活跃度进行分离,(因为不同 ...
- Postgresql分表与优化
--1.创建主表 CREATE TABLE tbl_partition ( date_key date, hour_key smallint, client_key integer, item_key ...
- WebGIS项目中利用mysql控制点库进行千万条数据坐标转换时的分表分区优化方案
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1. 背景 项目中有1000万条历史案卷,为某地方坐标系数据,我们的真实 ...
- Mysql性能优化三(分表、增量备份、还原)
接上篇Mysql性能优化二 对表进行水平划分 如果一个表的记录数太多了,比如上千万条,而且需要经常检索,那么我们就有必要化整为零了.如果我拆成100个表,那么每个表只有10万条记录.当然这需要数据在逻 ...
- C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本 - 大数据支持分表优化
公司的短信平台,数据量越来越大了,需要对数据进行一些优化,下面是拆分后的数据库量参考. 新开发的软件模块,必须支持分表,拆表的功能一个数据表里,不适合保存1000万以上的记录新开发的业务模块,能分表的 ...
- mysql中的优化, 简单的说了一下垂直分表, 水平分表(有几种模运算),读写分离.
一.mysql中的优化 where语句的优化 1.尽量避免在 where 子句中对字段进行表达式操作select id from uinfo_jifen where jifen/60 > 100 ...
- MYSQL性能优化分享(分库分表)
1.分库分表 很明显,一个主表(也就是很重要的表,例如用户表)无限制的增长势必严重影响性能,分库与分表是一个很不错的解决途径,也就是性能优化途径,现在的案例是我们有一个1000多万条记录的用户表mem ...
- Sql的分库分表,及优化
对Sql细节优化 在sql查询中为了提高查询效率,我们常常会采取一些措施对查询语句进行sql优化,下面总结的一些方法,有需要的可以参考参考. 首先给大家介绍一下分库分表 分库分表 分库 垂直分库 业务 ...
- Mysql MyISAM与InnoDB 表锁行锁以及分库分表优化
一. 两种存储引擎:MyISAM与InnoDB 区别与作用 1. count运算上的区别: 因为MyISAM缓存有表meta-data(行数等),因此在做COUNT(*)时对于一个结构很好的查询是不需 ...
- MySQL优化(一):MySQL分库分表
一.分库分表种类 1.垂直拆分 在考虑数据拆分的时候,一般情况下,应该先考虑垂直拆分.垂直可以理解为分出来的库表结构是互相独立各不相同的. - 如果有多个业务,每个业务直接关联性不大,那么就可以把每个 ...
随机推荐
- JavaWeb-SpringBoot_使用H2数据库实现用户注册登录
使用Gradle编译项目 传送门 前端资源同:使用MySQL数据库实现用户管理_demo 传送门 H2:SpringBoot内置持久化数据库 使用H2数据库实现用户注册登录 用户可以在index.h ...
- JavaWeb_响应和请求数据包
Google浏览器 F12中Network->Header部分 <%@ page language="java" import="java.util.*&qu ...
- 揭秘Android Studio项目目录结构
I don't know if this is because of the Gradle Build System (I'd wager it is), but I'll tell you what ...
- 分布式-信息方式-ActiveMQ静态网络连接信息回流功能
“丢失”的消息 有这样的场景, broker1和 broker2通过 netwoskconnector连接,一些 consumers连接到 broker1,消费 broker2上的消息.消息先被 br ...
- leetcode 83删除排序链表中的重复元素
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode ...
- golang入门案例之http client请求
发请求,接收接送,并解析 package main import ( "fmt" "net/http" "io/ioutil" " ...
- Android 动态申请权限
AndroidManifest.xml(清单文件)添加需要的权限 <uses-permission android:name="android.permission.ACCESS_CO ...
- tomcat gc和内存
tomcat启动参数,将JVM GC信息写入tomcat_gc.log CATALINA_OPTS='-Xms512m -Xmx4096m -XX:PermSize=64M -XX:MaxNewSiz ...
- Kafka sender消息生产者
1.pom文件引入Kafka依赖(我用的版本是2.2.2.RELEASE) <dependency> <groupId>org.springframework.kafka< ...
- MyView 的无奈问题
这不是为难我吗这种问题 据说这是内置库!!!!!可是: 找不到呀!!!!!!!!!! 后期补充: 是因为我的一个目录名字起了冲突