在 Kubernetes 上快速测试 Citus 分布式 PostgreSQL 集群(分布式表,共置,引用表,列存储)
准备工作
这里假设,你已经在 k8s
上部署好了基于 Citus
扩展的分布式 PostgreSQL
集群。
查看 Citus
集群(kubectl get po -n citus
),1 个 Coordinator(协调器)
节点 +
3 个 Worker(工作器)
节点。
NAME READY STATUS RESTARTS AGE
citus-coordinator-0 2/2 Running 0 3h55m
citus-worker-0 2/2 Running 0 22m
citus-worker-1 2/2 Running 0 21m
citus-worker-2 2/2 Running 0 21m
进入 coordinator
节点(kubectl -n citus exec -it citus-coordinator-0 -- bash
),查看活动的 worker
节点(psql 'host=citus-coordinator user=postgres' -c "SELECT * FROM citus_get_active_worker_nodes();"
)。
node_name | node_port
-----------------------------------------------------+-----------
citus-worker-1.citus-worker.citus.svc.cluster.local | 6432
citus-worker-2.citus-worker.citus.svc.cluster.local | 6432
citus-worker-0.citus-worker.citus.svc.cluster.local | 6432
(3 rows)
一旦拥有 Citus
集群,就可以开始创建分布式表
、引用表
和使用列存储
。
创建分布式表
create_distributed_table
将在本地或工作节点之间透明地切分您的表。
进入命令行工具:psql 'host=citus-coordinator user=postgres'
建表
CREATE TABLE events (
device_id bigint,
event_id bigserial,
event_time timestamptz default now(),
data jsonb not null,
PRIMARY KEY (device_id, event_id)
);
-- 将事件表分布在本地或工作节点上的分片上
SELECT create_distributed_table('events', 'device_id');
执行此操作后,对特定设备 ID
的查询将有效地路由到单个工作节点,而跨设备 ID
的查询将在集群中并行化。
插入一些事件
INSERT INTO events (device_id, data)
SELECT s % 100, ('{"measurement":'||random()||'}')::jsonb FROM generate_series(1,1000000) s;
-- INSERT 0 1000000
获取设备 1 的最后 3 个事件,路由到单个节点
命令行开启计时:postgres=# \timing
SELECT * FROM events WHERE device_id = 1 ORDER BY event_time DESC, event_id DESC LIMIT 3;
device_id | event_id | event_time | data
-----------+----------+-------------------------------+-------------------------------------
1 | 999901 | 2022-03-24 02:30:50.205478+00 | {"measurement": 0.8822990134507691}
1 | 999801 | 2022-03-24 02:30:50.205478+00 | {"measurement": 0.5239176115816448}
1 | 999701 | 2022-03-24 02:30:50.205478+00 | {"measurement": 0.9900647926398349}
(3 rows)
Time: 4.779 ms
解释跨分片并行化的查询的计划,以下显示了查询其中一个分片的计划以及如何完成跨分片的聚合
执行 sql
语句:
EXPLAIN (VERBOSE ON) SELECT count(*) FROM events;
QUERY PLAN
---------------------------------------------------------------------------------------------------------
Aggregate (cost=250.00..250.02 rows=1 width=8)
Output: COALESCE((pg_catalog.sum(remote_scan.count))::bigint, '0'::bigint)
-> Custom Scan (Citus Adaptive) (cost=0.00..0.00 rows=100000 width=8)
Output: remote_scan.count
Task Count: 32
Tasks Shown: One of 32
-> Task
Query: SELECT count(*) AS count FROM public.events_102008 events WHERE true
Node: host=citus-worker-0.citus-worker.citus.svc.cluster.local port=6432 dbname=postgres
-> Aggregate (cost=725.00..725.01 rows=1 width=8)
Output: count(*)
-> Seq Scan on public.events_102008 events (cost=0.00..650.00 rows=30000 width=0)
Output: device_id, event_id, event_time, data
(13 rows)
Time: 5.427 ms
使用共置(Co-location)创建分布式表
具有相同分布列的分布式表可以位于同一位置,以实现分布式表之间的高性能分布式连接(join)
和外键。 默认情况下,分布式表将根据分布列的类型位于同一位置,但您可以使用 create_distributed_table
中的 colocate_with
参数显式定义同一位置。
建表
CREATE TABLE devices (
device_id bigint primary key,
device_name text,
device_type_id int
);
CREATE INDEX ON devices (device_type_id);
-- 将设备表与事件表放在一起
SELECT create_distributed_table('devices', 'device_id', colocate_with := 'events');
插入设备元数据
INSERT INTO devices (device_id, device_name, device_type_id)
SELECT s, 'device-'||s, 55 FROM generate_series(0, 99) s;
可选:确保应用程序只能插入已知设备的事件
ALTER TABLE events ADD CONSTRAINT device_id_fk
FOREIGN KEY (device_id) REFERENCES devices (device_id);
获得跨分片并行的所有类型 55
设备的平均测量值
SELECT avg((data->>'measurement')::double precision)
FROM events JOIN devices USING (device_id)
WHERE device_type_id = 55;
avg
--------------------
0.4997412230952178
(1 row)
Time: 122.548 ms
Co-location
还可以帮助您扩展 INSERT..SELECT、存储过程和分布式事务。
- INSERT..SELECT
- 存储过程
- 分布式事务
创建引用表
当您需要不包含分布列的快速 join
或外键时,您可以使用 create_reference_table
在集群中的所有节点之间复制表。
建表
CREATE TABLE device_types (
device_type_id int primary key,
device_type_name text not null unique
);
跨所有节点复制表以在任何列上启用外键和 join
SELECT create_reference_table('device_types');
插入设备类型
INSERT INTO device_types (device_type_id, device_type_name) VALUES (55, 'laptop');
可选:确保应用程序只能插入已知类型的设备
ALTER TABLE devices ADD CONSTRAINT device_type_fk
FOREIGN KEY (device_type_id) REFERENCES device_types (device_type_id);
获取类型名称以笔记本电脑开头的设备的最后 3 个事件,跨分片并行
SELECT device_id, event_time, data->>'measurement' AS value, device_name, device_type_name
FROM events JOIN devices USING (device_id) JOIN device_types USING (device_type_id)
WHERE device_type_name LIKE 'laptop%' ORDER BY event_time DESC LIMIT 3;
device_id | event_time | value | device_name | device_type_name
-----------+-------------------------------+---------------------+-------------+------------------
31 | 2022-03-24 02:30:50.205478+00 | 0.9994211581289107 | device-31 | laptop
31 | 2022-03-24 02:30:50.205478+00 | 0.13771543211483106 | device-31 | laptop
88 | 2022-03-24 02:30:50.205478+00 | 0.5585740912470349 | device-88 | laptop
(3 rows)
Time: 96.537 ms
引用表使您能够扩展复杂的数据模型并充分利用关系数据库的功能。
使用列式存储创建表
要在 PostgreSQL
数据库中使用列式存储,您只需将 USING columnar 添加到 CREATE TABLE
语句中,您的数据将使用列式访问方法自动压缩。
建表
CREATE TABLE events_columnar (
device_id bigint,
event_id bigserial,
event_time timestamptz default now(),
data jsonb not null
)
USING columnar;
插入一些数据
INSERT INTO events_columnar (device_id, data)
SELECT d, '{"hello":"columnar"}' FROM generate_series(1,10000000) d;
创建一个基于行的表进行比较
CREATE TABLE events_row AS SELECT * FROM events_columnar;
查看表大小
postgres=# \d+
List of relations
Schema | Name | Type | Owner | Persistence | Access method | Size | Description
--------+------------------------------+----------+----------+-------------+---------------+------------+-------------
public | citus_tables | view | postgres | permanent | | 0 bytes |
public | device_types | table | postgres | permanent | heap | 8192 bytes |
public | devices | table | postgres | permanent | heap | 8192 bytes |
public | events | table | postgres | permanent | heap | 8192 bytes |
public | events_columnar | table | postgres | permanent | columnar | 25 MB |
public | events_columnar_event_id_seq | sequence | postgres | permanent | | 8192 bytes |
public | events_event_id_seq | sequence | postgres | permanent | | 8192 bytes |
public | events_row | table | postgres | permanent | heap | 806 MB |
(8 rows)
注意 events_row(806 MB)
与 events_columnar(25 MB)
的对比。压缩了几十倍,效果非常的惊人,大大节省了存储空间。
您可以单独使用列存储,也可以在分布式表中使用,以结合压缩和分布式查询引擎的优势。
使用列式存储时,您应该只使用 COPY
或 INSERT..SELECT
批量加载数据以实现良好的压缩。柱状表目前不支持更新、删除和外键。 但是,您可以使用分区表,其中较新的分区使用基于行的存储,而较旧的分区使用列存储进行压缩。
更多
- Citus 集群 - 官方快速入门教程
- Citus 集群 - 官方安装指南
- Citus 简介 - 将 Postgres 转换为分布式数据库
- Citus 架构及概念
- Citus 集群官方示例 - 多租户应用程序实战
- Citus 集群官方教程 - 迁移现有应用程序
- Citus 集群)官方示例 - 实时仪表盘
- Citus 集群)官方示例 - 时间序列数据
- 多租户数据库项目实战(Python/Django+Postgres+Citus)
- Citus 集群 - 分布式表中的分布列选择最佳实践
- 扩展分析处理服务(Smartly.io) - 使用 Citus 对 PostgreSQL 数据库进行分片
在 Kubernetes 上快速测试 Citus 分布式 PostgreSQL 集群(分布式表,共置,引用表,列存储)的更多相关文章
- Citus 分布式 PostgreSQL 集群 - SQL Reference(创建和修改分布式表 DDL)
创建和分布表 要创建分布式表,您需要首先定义表 schema. 为此,您可以使用 CREATE TABLE 语句定义一个表,就像使用常规 PostgreSQL 表一样. CREATE TABLE ht ...
- 分布式 PostgreSQL 集群(Citus),官方快速入门教程
多租户应用程序 在本教程中,我们将使用示例广告分析数据集来演示如何使用 Citus 来支持您的多租户应用程序. 注意 本教程假设您已经安装并运行了 Citus. 如果您没有运行 Citus,则可以使用 ...
- 分布式 PostgreSQL 集群(Citus)官方教程 - 迁移现有应用程序
将现有应用程序迁移到 Citus 有时需要调整 schema 和查询以获得最佳性能. Citus 扩展了 PostgreSQL 的分布式功能,但它不是扩展所有工作负载的直接替代品.高性能 Citus ...
- 分布式 PostgreSQL 集群(Citus)官方示例 - 时间序列数据
在时间序列工作负载中,应用程序(例如一些实时应用程序查询最近的信息,同时归档旧信息. https://docs.citusdata.com/en/v10.2/sharding/data_modelin ...
- 分布式 PostgreSQL 集群(Citus)官方安装指南
单节点 Citus Docker (Mac 与 Linux) Docker 镜像仅用于开发/测试目的, 并且尚未准备好用于生产用途. 您可以使用一个命令在 Docker 中启动 Citus: # st ...
- 分布式 PostgreSQL 集群(Citus),分布式表中的分布列选择最佳实践
确定应用程序类型 在 Citus 集群上运行高效查询要求数据在机器之间正确分布.这因应用程序类型及其查询模式而异. 大致上有两种应用程序在 Citus 上运行良好.数据建模的第一步是确定哪些应用程序类 ...
- Citus 分布式 PostgreSQL 集群 - SQL Reference(摄取、修改数据 DML)
插入数据 要将数据插入分布式表,您可以使用标准 PostgreSQL INSERT 命令.例如,我们从 Github 存档数据集中随机选择两行. INSERT http://www.postgresq ...
- Citus 分布式 PostgreSQL 集群 - SQL Reference(查询分布式表 SQL)
如前几节所述,Citus 是一个扩展,它扩展了最新的 PostgreSQL 以进行分布式执行.这意味着您可以在 Citus 协调器上使用标准 PostgreSQL SELECT 查询进行查询. Cit ...
- 分布式 PostgreSQL 集群(Citus)官方示例 - 实时仪表盘
Citus 提供对大型数据集的实时查询.我们在 Citus 常见的一项工作负载涉及为事件数据的实时仪表板提供支持. 例如,您可以是帮助其他企业监控其 HTTP 流量的云服务提供商.每次您的一个客户端收 ...
随机推荐
- 「BUAA OO Pre」Git生成多个ssh key并连接GitLab仓库
「BUAA OO Pre」Git生成多个ssh key并连接GitLab仓库 Part 0 前言 写作背景 笔者在配置学校GitLab的ssh key时遇到一些问题,原因应为曾经配置过GitHub的s ...
- Solution -「HEOI/TJOI 2016」「洛谷 P2824」排序
\(\mathcal{Description}\) Link. 给定排列 \(\{p_n\}\) 和 \(m\) 次局部排序操作,求操作完成后第 \(q\) 位的值. \(n,m\le10 ...
- MySQL安装,使用问题汇总
一,安装问题 mysqld install时出现:The service already exists! 报错原因:以前机器上装过mysql没有卸载干净 解决方案: C:\windows\system ...
- Java NIO Selector 的使用
之前的文章已经把 Java 中 NIO 的 Buffer.Channel 讲解完了,不太了解的可以先回过头去看看.这篇文章我们就来聊聊 Selector -- 选择器. 首先 Selector 是用来 ...
- NSSCTF-no_wakeup
打开网页是一个派萌的表情包(原神玩家手动狗头) 按照题目的提示点击,出现题目的源码, 观察题目源码,发现就是一个简单的反序列化,这边手打一下php (自己太菜了,枯了) <?phpclass H ...
- 大数据时代变局与机遇,BI数字化转型的实战攻略!
党的十九大报告提出,要推动互联网.大数据.人工智能和实体经济深度融合.更加高效地获取.运用信息,成为企业具有强大竞争力的重要标志.我国企业应牢牢把握历史性机遇,以更加开放的姿态,积极拥抱新经济,积极参 ...
- 【C# Task】TaskCompletionSource
TaskCompletionSource具体功能 用于封装一个没有不带委托的任务实列.可以在其他线程控制该任务实列什么时候结束.取消.错误.类似于EventWaitHandle的功能. 属性 Task ...
- mapreduce—shuffle图解
- xlrd》操作excel 出现的问题:File "D:\python37\lib\site-packages\xlrd\formula.py", line 1150, in evaluate_name_formula assert len(tgtobj.stack) == 1
xlrd>操作excel 出现的问题 报错如下: D:\python37\python.exe D:/testWang/waimai/tools/get_excelData.py*** for ...
- python如何data格式和时间戳的转换
Python 获取几天前的时间 计算几天前并转换为指定格式. import time import datetime # 先获得时间数组格式的日期 threeDayAgo = (datetime.da ...