数据库设计建议

1. 概述

本开发设计建议约定数据库建模和数据库应用程序开发过程中,应当遵守的设计规范。依据这些规范进行建模,能够更好的契合 openGauss 的分布式处理架构,输出更高效的业务 SQL 代码。

本开发设计建议中所陈述的 “建议” 和 “关注” 含义如下:

2. 数据库对象命名

数据库对象命名需要满足约束:非时序表长度不超过 63 个字节,时序表长度不超过 53 个字符,以字母或下划线开头,中间字符可以是字母、数字、下划线、$、#。

3. 数据库对象设计

3.1Database 和 Schema 设计

openGauss 中可以使用 Database 和 Schema 实现业务的隔离,区别在于 Database 的隔离更加彻底,各个 Database 之间共享资源极少,可实现连接隔离、权限隔离等,Database 之间无法直接互访。Schema 隔离的方式共用资源较多,可以通过 grant 与 revoke 语法便捷地控制不同用户对各 Schema 及其下属对象的权限。

Database 设计建议

Schema 设计建议


3.2 表设计

openGauss 是分布式架构。数据分布在各个 DN 上。总体上讲,良好的表设计需要遵循以下原则:

选择存储方案

【建议】表的存储类型是表定义设计的第一步,客户业务类型是决定表的存储类型的主要因素,表存储类型的选择依据请参考表 1。

表 1 表的存储类型及场景

存储类型

适用场景

行存

  • 点查询(返回记录少,基于索引的简单查询)。
  • 增、删、改操作较多的场景。

列存

  • 统计分析类查询(关联、分组操作较多的场景)。
  • 即席查询(查询条件不确定,行存表扫描难以使用索引)。

选择分布方案

【建议】表的分布方式的选择一般遵循以下原则:

表 2 表的分布方式及使用场景

分布方式

描述

适用场景

Hash

表数据通过 Hash 方式散列到数据库实例中的所有 DN 上。

数据量较大的事实表。

Replication

数据库实例中每一个 DN 都有一份全量表数据。

维度表、数据量较小的事实表。

Range

表数据对指定列按照范围进行映射,分布到对应 DN。

用户需要自定义分布规则的场景。

List

表数据对指定列按照具体值进行映射,分布到对应 DN。

用户需要自定义分布规则的场景。

选择分区方案


当表中的数据量很大时,应当对表进行分区,一般需要遵循以下原则:

典型的分区表定义如下:

复制代码CREATE TABLE staffS_p1
(
  staff_ID       NUMBER(6) not null,
  FIRST_NAME     VARCHAR2(20),
  LAST_NAME      VARCHAR2(25),
  EMAIL          VARCHAR2(25),
  PHONE_NUMBER   VARCHAR2(20),
  HIRE_DATE      DATE,
  employment_ID  VARCHAR2(10),
  SALARY         NUMBER(8,2),
  COMMISSION_PCT NUMBER(4,2),
  MANAGER_ID     NUMBER(6),
  section_ID     NUMBER(4)
)
PARTITION BY RANGE (HIRE_DATE)
( 
   PARTITION HIRE_19950501 VALUES LESS THAN ('1995-05-01 00:00:00'),
   PARTITION HIRE_19950502 VALUES LESS THAN ('1995-05-02 00:00:00'),
   PARTITION HIRE_maxvalue VALUES LESS THAN (MAXVALUE)
);

选择分布键


Hash 表的分布键选取至关重要,如果分布键选择不当,可能会导致数据倾斜,从而导致查询时,I/O 负载集中在部分 DN 上,影响整体查询性能。因此,在确定 Hash 表的分布策略之后,需要对表数据进行倾斜性检查,以确保数据的均匀分布。分布键的选择一般需要遵循以下原则:

3.3 字段设计

选择数据类型


字段设计时,基于查询效率的考虑,一般遵循以下原则:

常用字符串类型介绍

在进行字段设计时,需要根据数据特征选择相应的数据类型。字符串类型在使用时比较容易混淆,下表列出了 openGauss 中常见的字符串类型:

表 1 常用字符串类型

名称

描述

最大存储空间

CHAR(n)

定长字符串,n 描述了存储的字节长度,如果输入的字符串字节格式小于 n,那么后面会自动用空字符补齐至 n 个字节。

10MB

CHARACTER(n)

定长字符串,n 描述了存储的字节长度,如果输入的字符串字节格式小于 n,那么后面会自动用空字符补齐至 n 个字节。

10MB

NCHAR(n)

定长字符串,n 描述了存储的字节长度,如果输入的字符串字节格式小于 n,那么后面会自动用空字符补齐至 n 个字节。

10MB

BPCHAR(n)

定长字符串,n 描述了存储的字节长度,如果输入的字符串字节格式小于 n,那么后面会自动用空字符补齐至 n 个字节。

10MB

VARCHAR(n)

变长字符串,n 描述了可以存储的最大字节长度。

10MB

CHARACTER VARYING(n)

变长字符串,n 描述了可以存储的最大字节长度;此数据类型和 VARCHAR (n) 是同一数据类型的不同表达形式。

10MB

VARCHAR2(n)

变长字符串,n 描述了可以存储的最大字节长度,此数据类型是为兼容 Oracle 类型新增的,行为和 VARCHAR (n) 一致。

10MB

NVARCHAR2(n)

变长字符串,n 描述了可以存储的最大字节长度。

10MB

TEXT

不限长度(不超过 1GB-8203 字节)变长字符串。

1GB-8203 字节

3.4 约束设计

DEFAULT 和 NULL 约束

局部聚簇

Partial Cluster Key(局部聚簇,简称 PCK)是列存表的一种局部聚簇技术,在 openGauss 中,使用 PCK 可以通过 min/max 稀疏索引实现事实表快速过滤扫描。PCK 的选取遵循以下原则:

唯一约束

主键约束

外键约束

检查约束

3.5 视图和关联表设计

视图设计

关联表设计

4.JDBC 配置


目前,openGauss 相关的第三方工具都是通过 JDBC 进行连接的,此部分将介绍工具配置时的注意事项。

连接参数

复制代码
params = {
{ "user", user },
{ "database", database },
{ "client_encoding", "UTF8" },
{ "DateStyle", "ISO" },
{ "extra_float_digits", "2" },
{ "TimeZone",  createPostgresTimeZone() },
};

fetchsize

【关注】在应用程序中,如果需要使用 fetchsize,必须关闭 autocommit。开启 autocommit,会令 fetchsize 配置失效。

autocommit

【建议】在 JDBC 向 openGauss 申请连接的代码中,建议显式打开 autocommit 开关。如果基于性能或者其它方面考虑,需要关闭 autocommit 时,需要应用程序自己来保证事务的提交。例如,在指定的业务 SQL 执行完之后做显式提交,特别是客户端退出之前务必保证所有的事务已经提交。

释放连接

【建议】推荐使用连接池限制应用程序的连接数。每执行一条 SQL 就连接一次数据库,是一种不好的 SQL 编写习惯。

【建议】在应用程序完成作业任务之后,应当及时断开和 openGauss 的连接,释放资源。建议在任务中设置 session 超时时间参数。

【建议】使用 JDBC 连接池,在将连接释放给连接池前,需要执行以下操作,重置会话环境。否则,可能会产生因为历史会话信息导致的对象冲突。

CopyManager

【建议】在不使用 ETL 工具,数据入库实时性要求又比较高的情况下,建议在开发应用程序时,使用 openGauss JDBC 驱动的 copyManger 接口进行微批导入。

5.SQL 编写

DDL

数据加载和卸载

复制代码
INSERT INTO task(name,id,comment) VALUES ('task1','100','第100个任务');

类型转换

查询操作

宏名称

描述

示例

CURRENT_DATE

获取当前日期,不包含时分秒。

复制代码openGauss=# select CURRENT_DATE;
date
-———–
2018-02-02
(1 row)

CURRENT_TIME

获取当前时间,不包含年月日。

复制代码openGauss=# select CURRENT_TIME;
timetz
-——————-
00:39:34.633938+08
(1 row)

CURRENT_TIMESTAMP(n)

获取当前日期和时间,包含年月日时分秒。

说明:

n 表示存储的毫秒位数。

复制代码openGauss=# select CURRENT_TIMESTAMP(6);
timestamptz
-——————————
2018-02-02 00:39:55.231689+08
(1 row)
复制代码
SELECT id, (SELECT COUNT(*) FROM films f WHERE f.did = s.id) FROM staffs_p1 s;
复制代码
SELECT id, from_image_id, from_person_id, from_video_id FROM face_data WHERE current_timestamp(6) - time < '1 days'::interval;
复制代码
SELECT id, from_image_id, from_person_id, from_video_id FROM face_data where time >  current_timestamp(6) - '1 days'::interval;
复制代码
SELECT * FROM scdc.pub_menu 
WHERE (cdp= 300 AND inline=301) OR (cdp= 301 AND inline=302) OR (cdp= 302 ANDinline=301);
复制代码
SELECT * FROM scdc.pub_menu 
WHERE (cdp= 300 AND inline=301) 
union all
SELECT * FROM scdc.pub_menu 
WHERE (cdp= 301 AND inline=302) 
union all 
SELECT * FROM tablename 
WHERE (cdp= 302 AND inline=301)
复制代码
SELECT * FROM T1 WHERE T1.C1 NOT IN (SELECT T2.C2 FROM T2);

可以改写为:

复制代码  SELECT * FROM T1 WHERE NOT EXISTS (SELECT  * FROM T1,T2 WHERE T1.C1=T2.C2);

说明:

如果不能保证 T1.C1 列的值为 NOT NULL 的情况下,就不能进行上述改写。

如果 T1.C1 为子查询的输出,要根据业务逻辑确认其输出是否为 NOT NULL。

来源:https://my.oschina.net/gaussdb/blog/5486884

“做程序员,圈子和学习最重要”因为有有了圈子可以让你少走弯路,扩宽人脉,扩展思路,学习他人的一些经验及学习方法!同时在这分享一下是一直以来整理的Java后端进阶笔记文档和学习资料免费分享给大家!需要资料的朋友私信我扣【06】

数据库设计建议

展开阅读全文

页面更新:2024-03-08

标签:建议   数据库   字段   字符串   字节   对象   类型   操作   业务   数据

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top