PostgreSQL表分区详解

表分区是一种非常有效的技术,用于提高大型数据库表的性能。通过将表的内容划分为较小的子表(称为分区),可以减小表的整体大小,从而显着提高性能。

什么时候应该对表进行分区?

  • 如果您的表对于服务器的 RAM 来说太大。您应该考虑对其进行分区:当表的大小达到几 GB 时,就该将其拆分。
  • 如果您正在处理大量数据,那么在拥有数百万条记录之前,不必费心进行分区。否则,您不会看到太多的性能提升。
  • 如果您的表可以在逻辑上分解为更小的块,例如:您有一个充满服务器日志的表。您可以按日期将它们拆分,因此同一天的所有日志都位于一个分区中。这使得执行诸如删除旧日志之类的任务变得更加容易,只需删除分区即可。

Postgres 内置支持三种类型的分区:

按range范围分区

该表被分区为由键列或一组列定义的“范围ranges”,分配给不同分区的值范围之间没有重叠

在以下示例中,人员表将按birth_date分区

CREATE TABLE people (
    id **int** not **null**,
    birth\_date date not **null**,
    country\_code character(2) not **null**,
    name text
) PARTITION BY RANGE (birth\_date);

CREATE TABLE people\_y2000 PARTITION OF people
    FOR VALUES FROM ('2000-01-01') TO ('2001-01-01');

CREATE TABLE people\_y2001 PARTITION OF people
    FOR VALUES FROM ('2001-01-01') TO ('2002-01-01');

CREATE TABLE people\_y2002 PARTITION OF people
    FOR VALUES FROM ('2002-01-01') TO ('2003-01-01');

我们来尝试一下:


INSERT INTO people (id, birth\_date, country\_code, name) VALUES
   (1, '2000-01-01', 'US', 'John'),
   (2, '2000-02-02', 'IT', 'Jane'),
   (3, '2001-03-03', 'FR', 'Bob');
> INSERT 0 3

SELECT schemaname,relname,n\_live\_tup 
   FROM pg\_stat\_user\_tables 
   ORDER BY n\_live\_tup DESC;

schemaname  |   relname    | n\_live\_tup 
------------+--------------+------------
 **public**     | people\_y2000 |          2
 **public**     | people\_y2001 |          1
 **public**     | people\_y2002 |          0

我们在主表people 中插入了三条记录。由于该表是按birth_date分区的,因此已将两条记录添加到分区people_y2000中,一条记录添加到people_y2001中,而people_y2002仍然为空。

按列表分区

通过显式列出每个分区中出现的键值来对表进行分区。

以同一示例为例,我们添加一个country_code列并将其用作分区键


CREATE TABLE people (
    id **int** not **null**,
    birth\_date date not **null**,
    country\_code character(2) not **null**,
    name text
) PARTITION BY LIST (country\_code);

-- Partition **for** people living in Europe
CREATE TABLE people\_EU PARTITION OF people
    FOR VALUES IN ('AT', 'DE', 'IT', 'FR', 'ES', ..... );

-- Partition **for** people living in United States
CREATE TABLE people\_US PARTITION OF people
    FOR VALUES IN ('US');

我们来尝试一下:


INSERT INTO people (id, birth\_date, country\_code, name) VALUES
   (1, '2000-01-01', 'US', 'John'),
   (2, '2000-02-02', 'IT', 'Jane'),
   (3, '2001-03-03', 'FR', 'Bob');
> INSERT 0 3

SELECT schemaname,relname,n\_live\_tup 
   FROM pg\_stat\_user\_tables 
   ORDER BY n\_live\_tup DESC;

 schemaname |  relname  | n\_live\_tup 
------------+-----------+------------
 **public**     | people\_eu |          2
 **public**     | people\_us |          1

PostgreSQL 再次将每一行移动到正确的分区。

按哈希分区

通过为每个分区指定模数和余数来对表进行分区。每个分区将保存分区键的哈希值除以指定模数将产生指定余数的行。

当我们无法逻辑地划分数据,但我们只能通过将行分散到许多较小的分区来减小表大小时,这种类型非常有用。

下面的 SQL 将把人分成三个表,每个表将包含(几乎)相同的行数。

我们来尝试一下:


INSERT INTO people (id, birth\_date, country\_code, name) VALUES
   (1, '2000-01-01', 'US', 'John'),
   (2, '2000-02-02', 'IT', 'Jane'),
   (3, '2001-03-03', 'FR', 'Bob');
> INSERT 0 3

SELECT schemaname,relname,n\_live\_tup 
   FROM pg\_stat\_user\_tables 
   ORDER BY n\_live\_tup DESC;

 schemaname | relname  | n\_live\_tup 
------------+----------+------------
 **public**     | people\_1 |          1
 **public**     | people\_2 |          1
 **public**     | people\_3 |          1

正如您所看到的,这三个记录已均匀地分布在所有可用分区中。

默认分区

当您尝试插入无法放入任何分区的记录时会发生什么?

让我们回到列表分区章节中定义的 people 表,并尝试添加来自加拿大的 Linda:


INSERT INTO people (id, birth\_date, country\_code, name) VALUES
   (4, '2002-04-04', 'CA', 'Linda');

ERROR:  no partition of relation "people" found **for** rowDETAILS: Partition key of the failing row contains (country\_code) = (CA). 

INSERT 将失败,因为 PostgreSQL 不知道在哪里添加该记录。

最明显的解决方案是添加一个新分区,但如果我们必须为世界上的每个国家/地区执行此操作,我们最终会得到数百个记录数量很少的表。不太好。

幸运的是,可以定义默认分区!

CREATE TABLE people_default PARTITION OF people DEFAULT;

再次尝试相同的插入,将导致:

INSERT INTO people (id, birth\_date, country\_code, name) VALUES
   (1, '2000-01-01', 'US', 'John'),
   (2, '2000-02-02', 'IT', 'Jane'),
   (3, '2001-03-03', 'FR', 'Bob'),
   (4, '2002-04-04', 'CA', 'Linda');
> INSERT 0 4

schemaname |    relname     | n\_live\_tup 
------------+----------------+------------
 **public**     | people\_eu      |          2
 **public**     | people\_us      |          1
 **public**     | people\_**default** |          1

如您所见,Linda 现已添加到people_default中。[https://www.jdon.com/67666.html](URL Here)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/24291.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ安装说明文档-v2.0

rabbitmq安装 说明:请使用资料里提供的CentOS-7-x86_64-DVD-1810.iso 安装虚拟机. 1. 安装依赖环境 在线安装依赖环境: yum install build-essential openssl openssl-devel unixODBC unixODBC-devel make gcc gcc-c kernel-devel m4 ncurses-devel …

【并发专题】单例模式的线程安全(进阶理解篇)

目录 背景前置知识类加载运行全过程 单例模式的实现方式一、饿汉式基本介绍源码分析 二、懒汉式基本介绍源码分析改进 三、懒汉式单例终极解决方案(静态内部类)(推荐使用方案)基本介绍源码分析 感谢 背景 最近学习了JVM之后&…

面试题:JS如何最快的执行垃圾回收机制

因为没看见答案,所以也不知道对不对。 JavaScript 的垃圾回收机制是由 JavaScript 引擎自动管理的,通常情况下我们无法控制垃圾回收机制的执行时间和频率。 然而,我们可以采取一些优化策略来减少垃圾回收的性能开销,从而提高代码…

Ubuntu20.04 GNOME桌面root用户无法登录,错误:sorry that didn‘t work please try again

WSL2的Ubuntu20.04安装了GNOME桌面环境,Ubuntu安装xrdp,使用windows自带的远程桌面连接工具连接,直接使用root用户登录的话,第一次可以正常登录(会提示你不推荐使用root用户登录),第二次登录就提…

golang函数传参——值传递理解

做了五年的go开发,却并没有什么成长,都停留在了业务层面了。一直以为golang中函数传参,如果传的是引用类型,则是以引用传递,造成这样的误解,实在也不能怪我。我们来看一个例子,众所周知&#xf…

uniapp发布插件显示components/xxx文件没找到,插件格式不正确

uniapp发布插件显示components/xxx文件没找到,插件格式不正确 将插件文件这样一起选中,然后右键压缩成zip文件,而不是外层文件压缩

记一次 .NET某医疗器械清洗系统 卡死分析

一:背景 1. 讲故事 前段时间协助训练营里的一位朋友分析了一个程序卡死的问题,回过头来看这个案例比较经典,这篇稍微整理一下供后来者少踩坑吧。 二:WinDbg 分析 1. 为什么会卡死 因为是窗体程序,理所当然就是看主…

MYSQL事务同时修改单条记录

疑问:Mysql多事务默认情况下,同时修改同一条记录运行修改吗?是否要手动加上for update行锁。 猜想:MySQL 会自动对涉及的数据行加上写锁(排他锁),以确保数据的一致性和隔离性。这是在默认的事务…

SQL ASNI where from group order 顺序

SQL语句执行顺序: from–>where–>group by -->having — >select --> order 第一步:from语句,选择要操作的表。 第二步:where语句,在from后的表中设置筛选条件,筛选出符合条件的记录。 …

PyTorch深度学习实战(9)——学习率优化

PyTorch深度学习实战(9)——学习率优化 0. 前言1. 学习率简介2. 梯度值、学习率和权重之间的相互作用3. 学习率优化实战3.1 学习率对缩放后的数据集的影响3.2 学习率对未缩放数据集的影响 小结系列链接 0. 前言 学习率( learning rate )是神经网络训练中…

从0到1开发go-tcp框架【4实战片— — 开发MMO之玩家聊天篇】

从0到1开发go-tcp框架【实战片— — 开发MMO】 MMO(MassiveMultiplayerOnlineGame):大型多人在线游戏(多人在线网游) 1 AOI兴趣点的算法 游戏中的坐标模型: 场景相关数值计算 ● 场景大小: 250…

解密爬虫ip是如何被识别屏蔽的

在当今信息化的时代,网络爬虫已经成为许多企业、学术机构和个人不可或缺的工具。然而,随着网站安全防护的升级,爬虫ip往往容易被识别并屏蔽,给爬虫工作增加了许多困扰。在这里,作为一家专业的爬虫ip供应商,…

Control files of Oracle

控制文件是数据库建立的时候自动生成的二进制文件,只能通过实例进行修改,如果手动修改的话会造成控制文件与物理信息不符合,从而导致数据库不能正常工作。oracle数据库通过控制文件保持数据库的完整性,一旦控制文件被破坏数据库将…

PAT(Advanced Level)刷题指南 —— 第三弹

一、1102 Invert a Binary Tree 1. 问题重述 每个输入文件包含一个测试,第一行给定一个正整数 N (≤10) 表示二叉树的总结点数目。因此节点从 0 到 N -1 进行编号。接下来N行,每行对应从 0 到 N -1 的结点,并且给定每个结点的左右孩子结点的索引。如果这个结点的孩子节点不…

C# 根据前台传入实体名称,动态查询数据

前言: 项目中时不时遇到查字典表等数据,只需要返回数据,不需要写其他业务,每个字典表可能都需要写一个接口给前端调用,比较麻烦,所以采用下面这种方式,前端只需传入实体名称即可,例…

某小厂面试

某小厂面试 1.spring ioc aop2.arraylist和linkedlist哪个查询快3.java基本数据类型4.自动装箱拆箱5.关系型数据库用过吗6.mysql连接方式7.内连接和外连接8.主键和外键 1.spring ioc aop IOC(Inversion of Control)是一种设计原则,它将原本由…

2023上半年手机及数码行业分析报告(京东销售数据分析)

2023年上半年,手机市场迎来复苏,同环比来看,销量销额纷纷上涨。 而数码市场中,各个热门品类表现不一。微单相机及智能手表同比去年呈现增长态势,而笔记本电脑市场则出现下滑。 基于此现状,鲸参谋发布了20…

谈一谈Python中的装饰器

1、装饰器基础介绍 1.1 何为Python中的装饰器? Python中装饰器的定义以及用途: 装饰器是一种特殊的函数,它可以接受一个函数作为参数,并返回一个新的函数。装饰器可以用来修改或增强函数的行为,而不需要修改函数本身…

JVM深入 —— JVM的体系架构

前言 能否真正理解JVM的底层实现原理是进阶Java技术的必由之路,Java通过JVM虚拟机的设计使得Java的延拓性更好,平台无关性是其同时兼顾移动端和服务器端开发的重要特性。在本篇文章中,荔枝将会仔细梳理JVM的体系架构和理论知识,希…

flutter开发实战-RawKeyboardListener监听键盘事件及keycode。

flutter开发实战-RawKeyboardListener监听键盘事件及keycode。 最近开发过程中遇到外设备的按钮点击触发相应的操作,需要监听对应的keycode来开启游戏或者相关操作。 这里用到了RawKeyboardListener 一、RawKeyboardListener是什么? RawKeyboardListe…