From e45dc3ff9bf6cd733ced18a5ce87cfdf0d11eaa0 Mon Sep 17 00:00:00 2001
From: li-jun056 <1255728208@qq.com>
Date: Tue, 17 Nov 2020 14:36:26 +0800
Subject: [PATCH 1/2] add documents
---
...77\347\224\250\345\267\256\345\274\202.md" | 163 ++++++++
...30\344\270\216\345\210\227\345\255\230.md" | 348 ++++++++++++++++++
content/zh/post/gaoyunlong/title/title.PNG | Bin 0 -> 148750 bytes
...1\205\215openGauss\347\232\204exporter.md" | 206 +++++++++++
...b_ef290bfc-0cea-11eb-bd37-38f9d3cd240d.png | Bin 0 -> 7385 bytes
...PG\347\232\204\345\257\271\346\257\224.md" | 169 +++++++++
.../post/shujukujiagouzhimei/title/title.PNG | Bin 0 -> 66204 bytes
.../xiaoxiaoliang/figures/\345\233\2761.png" | Bin 0 -> 59845 bytes
.../xiaoxiaoliang/figures/\345\233\2762.png" | Bin 0 -> 22841 bytes
...50\350\241\250\347\261\273\345\236\213.md" | 32 ++
content/zh/post/xiaoxiaoliang/title/title.PNG | Bin 0 -> 163555 bytes
11 files changed, 918 insertions(+)
create mode 100644 "content/zh/post/gaoyunlong/openGauss\344\270\216-postgresql\346\227\245\345\270\270\344\275\277\347\224\250\345\267\256\345\274\202.md"
create mode 100644 "content/zh/post/gaoyunlong/openGauss\350\241\214\345\255\230\344\270\216\345\210\227\345\255\230.md"
create mode 100644 content/zh/post/gaoyunlong/title/title.PNG
create mode 100644 "content/zh/post/gaoyunlong/\351\200\202\351\205\215openGauss\347\232\204exporter.md"
create mode 100644 content/zh/post/shujukujiagouzhimei/figures/modb_ef290bfc-0cea-11eb-bd37-38f9d3cd240d.png
create mode 100644 "content/zh/post/shujukujiagouzhimei/openGauss\344\270\255\347\232\204\345\271\266\350\241\214\345\233\236\346\224\276\344\273\245\345\217\212\345\222\214PG\347\232\204\345\257\271\346\257\224.md"
create mode 100644 content/zh/post/shujukujiagouzhimei/title/title.PNG
create mode 100644 "content/zh/post/xiaoxiaoliang/figures/\345\233\2761.png"
create mode 100644 "content/zh/post/xiaoxiaoliang/figures/\345\233\2762.png"
create mode 100644 "content/zh/post/xiaoxiaoliang/openGauss\345\205\274\345\256\271Oracle\346\225\260\346\215\256\347\261\273\345\236\213\345\222\214\345\270\270\347\224\250\350\241\250\347\261\273\345\236\213.md"
create mode 100644 content/zh/post/xiaoxiaoliang/title/title.PNG
diff --git "a/content/zh/post/gaoyunlong/openGauss\344\270\216-postgresql\346\227\245\345\270\270\344\275\277\347\224\250\345\267\256\345\274\202.md" "b/content/zh/post/gaoyunlong/openGauss\344\270\216-postgresql\346\227\245\345\270\270\344\275\277\347\224\250\345\267\256\345\274\202.md"
new file mode 100644
index 00000000..93cc649f
--- /dev/null
+++ "b/content/zh/post/gaoyunlong/openGauss\344\270\216-postgresql\346\227\245\345\270\270\344\275\277\347\224\250\345\267\256\345\274\202.md"
@@ -0,0 +1,163 @@
++++
+
+title = "openGauss与 postgresql日常使用差异"
+
+date = "2020-11-17"
+
+tags = ["openGauss与 postgresql日常使用差异"]
+
+archives = "2020-11"
+
+author = "高云龙"
+
+summary = "openGauss与 postgresql日常使用差异"
+
+img = "/zh/post/gaoyunlong/title/title.png"
+
+times = "12:40"
+
++++
+
+# openGauss与 postgresql日常使用差异
+
+## 密码加密
+
+- postgresql默认密码加密方式是md5。
+
+- openGauss默认密码加密方式是sha256。
+- 使用navicate、pgadmin3等客户端开发工具访问og,需要修改加密方式。
+- 如果在本地用用户名密码登陆数据库没问题。
+- 但是用其他工具连接数据库报用户或密码错误。
+- 可能是密码加密方式不对,需要看pg\_hba.conf 及 参数。
+
+```
+password_encryption_type = 0 #Password storage type, 0 is md5 for PG, 1 is sha256 + md5, 2 is sha256 only
+```
+
+## 字符串存储
+
+在postgresql里,char\(n\)、varchar\(n\) n代表是字符;最多存储1GB。
+
+在openGauss里,char\(n\)、varcahr\(n\) n代表的是字节,nvarchar2\(n\) n代表是字符;最多存储100MB。
+
+```
+---
+---postgresql字符测试
+---
+postgres=# \d dt
+ Table "public.dt"
+ Column | Type | Collation | Nullable | Default
+--------+----------------------+-----------+----------+---------
+ id | integer | | |
+ col1 | character varying(8) | | |
+
+postgres=# insert into dt values(3,'中文字符长度测试');
+INSERT 0 1
+postgres=# insert into dt values(4,'yingwen8');
+INSERT 0 1
+postgres=# insert into dt values(4,'yingwen88');
+ERROR: value too long for type character varying(8)
+
+---
+---openGauss字符测试
+---
+mydb=# \d+ dt
+ Table "public.dt"
+ Column | Type | Modifiers | Storage | Stats target | Description
+--------+----------------------+-----------+----------+--------------+-------------
+ id | integer | | plain | |
+ col1 | character varying(8) | | extended | |
+ col2 | nvarchar2(8) | | extended | |
+Has OIDs: no
+Options: orientation=row, compression=no
+
+mydb=# insert into dt(id,col1) values(3,'yingwen8');
+INSERT 0 1
+mydb=# insert into dt(id,col1) values(3,'yingwen88');
+ERROR: value too long for type character varying(8)
+CONTEXT: referenced column: col1
+mydb=# insert into dt(id,col1) values(3,'中文测试');
+ERROR: value too long for type character varying(8)
+CONTEXT: referenced column: col1
+mydb=# insert into dt(id,col1) values(3,'中文测');
+ERROR: value too long for type character varying(8)
+CONTEXT: referenced column: col1
+
+mydb=# insert into dt(id,col2) values(4,'中文字符长度测试');
+INSERT 0 1
+mydb=# insert into dt(id,col2) values(4,'yingwen8');
+INSERT 0 1
+mydb=# insert into dt(id,col2) values(4,'yingwen88');
+ERROR: value too long for type nvarchar2(8)
+CONTEXT: referenced column: col2
+mydb=#
+```
+
+## null 与 空字符
+
+- 在postgresql里 null != ‘’
+
+- 在openGauss里‘’转换成 null,没有‘’
+
+----+------
+
+```
+---
+---postgresql测试
+---
+postgres=# create table dt(id int,col1 varchar(8));
+CREATE TABLE
+postgres=# insert into dt values(1,null);
+INSERT 0 1
+postgres=# insert into dt values(2,'');
+INSERT 0 1
+postgres=# select * from dt;
+ id | col1
+----+------
+ 1 |
+ 2 |
+(2 rows)
+
+postgres=# select * from dt where col1 is null;
+ id | col1
+----+------
+ 1 |
+(1 row)
+
+postgres=# select * from dt where col1='';
+ id | col1
+----+------
+ 2 |
+(1 row)
+
+postgres=#
+---
+---openGauss测试
+---
+mydb=# create table dt(id int,col1 varchar(8));
+CREATE TABLE
+mydb=# insert into dt values(1,null);
+INSERT 0 1
+mydb=# insert into dt values(1,'');
+INSERT 0 1
+mydb=# select * from dt;
+ id | col1
+----+------
+ 1 |
+ 1 |
+(2 rows)
+
+mydb=# select * from dt where col1 is null;
+ id | col1
+----+------
+ 1 |
+ 1 |
+(2 rows)
+
+mydb=# select * from dt where col1='';
+ id | col1
+----+------
+(0 rows)
+
+mydb=#
+```
diff --git "a/content/zh/post/gaoyunlong/openGauss\350\241\214\345\255\230\344\270\216\345\210\227\345\255\230.md" "b/content/zh/post/gaoyunlong/openGauss\350\241\214\345\255\230\344\270\216\345\210\227\345\255\230.md"
new file mode 100644
index 00000000..58a1e322
--- /dev/null
+++ "b/content/zh/post/gaoyunlong/openGauss\350\241\214\345\255\230\344\270\216\345\210\227\345\255\230.md"
@@ -0,0 +1,348 @@
++++
+
+title = "openGauss行存与列存"
+
+date = "2020-11-17"
+
+tags = ["openGauss行存与列存"]
+
+archives = "2020-11"
+
+author = "高云龙"
+
+summary = "openGauss行存与列存"
+
+img = "/zh/post/gaoyunlong/title/title.png"
+
+times = "12:30"
+
++++
+
+# openGauss行存与列存
+
+## 列存表限制
+
+- 列存表不支持数组。
+- 列存表的数量建议不超过1000个。
+- 列存表的表级约束只支持PARTIAL CLUSTER KEY,不支持主外键等表级约束。
+- 列存表的字段约束只支持NULL、NOT NULL和DEFAULT常量值。
+- 列存表不支持alter命令修改字段约束。
+- 列存表支持delta表,受参数enable\_delta\_store 控制是否开启,受参数deltarow\_threshold控制进入delta表的阀值。
+
+## 列存相关参数
+
+- cstore\_buffers
+
+ 列存所使用的共享缓冲区的大小,默认值:32768KB。
+
+
+- partition\_mem\_batch
+
+ 指定缓存个数,为了优化对列存分区表的批量插入,在批量插入过程中会对数据进行缓存后再批量写盘。默认值:256 。
+
+
+- partition\_max\_cache\_size
+
+ 指定数据缓存区大小,为了优化对列存分区表的批量插入,在批量插入过程中会对数据进行缓存后再批量写盘。默认值:2GB。
+
+
+- enable\_delta\_store
+
+ 为了增强列存单条数据导入的性能和解决磁盘冗余问题,是否需要开启列存delta表功能,与参数DELTAROW\_THRESHOLD 配合使用。默认值:off。
+
+
+## 建表语法
+
+openGauss 创建普通表默认是未压缩的行存表。
+
+```
+mydb=# \dt
+No relations found.
+mydb=# create table test_t(id serial primary key ,col1 varchar(8),col2 decimal(6,2),create_time timestamptz not null default now());
+NOTICE: CREATE TABLE will create implicit sequence "test_t_id_seq" for serial column "test_t.id"
+NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_t_pkey" for table "test_t"
+CREATE TABLE
+mydb=# \dt+
+ List of relations
+ Schema | Name | Type | Owner | Size | Storage | Description
+--------+--------+-------+-------+---------+----------------------------------+-------------
+ public | test_t | table | omm | 0 bytes | {orientation=row,compression=no} |
+(1 row)
+
+mydb=#
+```
+
+创建列存表,需要指定**orientation=column**,默认压缩级别是low。
+
+```
+mydb=# create table column_t(id serial,col1 varchar(8),col2 decimal(6,2),create_time timestamptz not null default now()) with (orientation=column );
+NOTICE: CREATE TABLE will create implicit sequence "column_t_id_seq" for serial column "column_t.id"
+CREATE TABLE
+mydb=# \dt+
+ List of relations
+ Schema | Name | Type | Owner | Size | Storage | Description
+--------+----------+-------+-------+---------+--------------------------------------+-------------
+ public | column_t | table | omm | 16 kB | {orientation=column,compression=low} |
+ public | test_t | table | omm | 0 bytes | {orientation=row,compression=no} |
+(2 rows)
+
+mydb=#mydb=# \d+ column_t
+ Table "public.column_t"
+ Column | Type | Modifiers | Storage | Stats target | Description
+-------------+--------------------------+-------------------------------------------------------+----------+--------------+-------------
+ id | integer | not null default nextval('column_t_id_seq'::regclass) | plain | |
+ col1 | character varying(8) | | extended | |
+ col2 | numeric(6,2) | | main | |
+ create_time | timestamp with time zone | not null default now() | plain | |
+Has OIDs: no
+Options: orientation=column, compression=low
+```
+
+列存表添加局部聚簇存储列。
+
+```
+mydb=# \d+ column_t
+ Table "public.column_t"
+ Column | Type | Modifiers | Storage | Stats target | Description
+-------------+--------------------------+-------------------------------------------------------+----------+--------------+-------------
+ id | integer | not null default nextval('column_t_id_seq'::regclass) | plain | |
+ col1 | character varying(8) | | extended | |
+ col2 | numeric(6,2) | | main | |
+ create_time | timestamp with time zone | not null default now() | plain | |
+Has OIDs: no
+Options: orientation=column, compression=low
+
+mydb=# alter table column_t add PARTIAL CLUSTER KEY(id);
+ALTER TABLE
+mydb=# \d+ column_t
+ Table "public.column_t"
+ Column | Type | Modifiers | Storage | Stats target | Description
+-------------+--------------------------+-------------------------------------------------------+----------+--------------+-------------
+ id | integer | not null default nextval('column_t_id_seq'::regclass) | plain | |
+ col1 | character varying(8) | | extended | |
+ col2 | numeric(6,2) | | main | |
+ create_time | timestamp with time zone | not null default now() | plain | |
+Partial Cluster :
+ "column_t_cluster" PARTIAL CLUSTER KEY (id)
+Has OIDs: no
+Options: orientation=column, compression=low
+
+mydb=#
+```
+
+直接创建带局部聚簇存储的列存表。
+
+```
+NOTICE: CREATE TABLE will create implicit sequence "column_c_id_seq" for serial column "column_c.id"
+CREATE TABLE
+mydb=# \d+ column_c
+ Table "public.column_c"
+ Column | Type | Modifiers | Storage | Stats target | Description
+-------------+--------------------------+-------------------------------------------------------+----------+--------------+-------------
+ id | integer | not null default nextval('column_c_id_seq'::regclass) | plain | |
+ col1 | character varying(8) | | extended | |
+ col2 | numeric(6,2) | | main | |
+ create_time | timestamp with time zone | not null default now() | plain | |
+Partial Cluster :
+ "column_c_cluster" PARTIAL CLUSTER KEY (id)
+Has OIDs: no
+Options: orientation=column, compression=low
+
+mydb=#
+```
+
+## 列存与行存对比
+
+**磁盘使用空间**
+
+- 列存表默认大小16K,low压缩级别。
+- 行存表默认大小0bytes,非压缩级别。
+- 分别向两个表中插入100万条数据,占用磁盘大小对比。
+
+```
+mydb=# \dt+
+ List of relations
+ Schema | Name | Type | Owner | Size | Storage | Description
+--------+-----------+-------+-------+---------+-----------------------------------------+-------------
+ public | column_t | table | omm | 16 kB | {orientation=column,compression=low} |
+ public | column_th | table | omm | 16 kB | {orientation=column,compression=high} |
+ public | column_tm | table | omm | 16 kB | {orientation=column,compression=middle} |
+ public | row_tc | table | omm | 0 bytes | {orientation=row,compression=yes} |
+ public | test_t | table | omm | 0 bytes | {orientation=row,compression=no} |
+(5 rows)
+
+mydb=# insert into column_t select generate_series(1,1000000),left(md5(random()::text),8),random()::numeric(6,2);
+INSERT 0 1000000
+Time: 11328.880 ms
+mydb=# insert into column_th select generate_series(1,1000000),left(md5(random()::text),8),random()::numeric(6,2);
+INSERT 0 1000000
+Time: 10188.634 ms
+mydb=# insert into column_tm select generate_series(1,1000000),left(md5(random()::text),8),random()::numeric(6,2);
+INSERT 0 1000000
+Time: 9802.739 ms
+mydb=# insert into test_t select generate_series(1,1000000),left(md5(random()::text),8),random()::numeric(6,2);
+INSERT 0 1000000
+Time: 17404.945 ms
+mydb=# insert into row_tc select generate_series(1,1000000),left(md5(random()::text),8),random()::numeric(6,2);
+INSERT 0 1000000
+Time: 12394.866 ms
+mydb=# \dt+
+ List of relations
+ Schema | Name | Type | Owner | Size | Storage | Description
+--------+-----------+-------+-------+----------+-----------------------------------------+-------------
+ public | column_t | table | omm | 12 MB | {orientation=column,compression=low} |
+ public | column_th | table | omm | 8304 kB | {orientation=column,compression=high} |
+ public | column_tm | table | omm | 10168 kB | {orientation=column,compression=middle} |
+ public | row_tc | table | omm | 58 MB | {orientation=row,compression=yes} |
+ public | test_t | table | omm | 58 MB | {orientation=row,compression=no} |
+(5 rows)
+
+mydb=#
+```
+
+- 列存表开启的压缩级别越高。
+- 占用磁盘空间越少行存表开启压缩后,磁盘空间大小占比减少不明显。
+- 列存表占用磁盘空间比行存表占用磁盘空间少近6倍。
+
+**DML对比**
+
+查找单列
+
+```
+---
+---按范围查找,列存比行存快近20倍
+---
+mydb=# select col1 from test_t where id>=100010 and id<100020;
+ col1
+----------
+ 4257a3f3
+ 3d397284
+ 64343438
+ 6eb7bdb7
+ d1c9073d
+ 6aeb037c
+ 1d424974
+ 223235ab
+ 329de235
+ 2f02adc1
+(10 rows)
+
+Time: 77.341 ms
+mydb=# select col1 from column_t where id>=100010 and id<100020;
+ col1
+----------
+ d4837c30
+ 87a46f7a
+ 2f42a9c9
+ 4481c793
+ 68800204
+ 613b9205
+ 9d8f4a0a
+ 5cc4ff9e
+ f948cd10
+ f2775cee
+(10 rows)
+
+Time: 3.884 ms
+
+---
+---随机查找,列存比行存快近35倍
+---
+
+mydb=# select col1 from test_t limit 10;
+ col1
+----------
+ c2780d93
+ 294be14d
+ 4e53b761
+ 2c10f8a2
+ ae776743
+ 7d683c66
+ b3b40054
+ 7e56edf9
+ a7b7336e
+ ea3d47d9
+(10 rows)
+
+Time: 249.887 ms
+mydb=# select col1 from column_t limit 10;
+ col1
+----------
+ a745d77b
+ 4b6df494
+ 76fed9c1
+ 70c9664d
+ 3384de8a
+ 4158f3bf
+ 5d1c3b9f
+ 341876bb
+ f396f4ed
+ abfd78bb
+(10 rows)
+
+Time: 7.738 ms
+```
+
+select \*
+
+```
+---
+---行存比列存查询快30%
+---
+mydb=# select * from test_t limit 10;
+ id | col1 | col2 | create_time
+----+----------+------+-------------------------------
+ 1 | c2780d93 | .37 | 2020-10-26 14:27:33.304108+08
+ 2 | 294be14d | .57 | 2020-10-26 14:27:33.304108+08
+ 3 | 4e53b761 | .98 | 2020-10-26 14:27:33.304108+08
+ 4 | 2c10f8a2 | .27 | 2020-10-26 14:27:33.304108+08
+ 5 | ae776743 | .97 | 2020-10-26 14:27:33.304108+08
+ 6 | 7d683c66 | .58 | 2020-10-26 14:27:33.304108+08
+ 7 | b3b40054 | .44 | 2020-10-26 14:27:33.304108+08
+ 8 | 7e56edf9 | .43 | 2020-10-26 14:27:33.304108+08
+ 9 | a7b7336e | .31 | 2020-10-26 14:27:33.304108+08
+ 10 | ea3d47d9 | .42 | 2020-10-26 14:27:33.304108+08
+(10 rows)
+
+Time: 6.822 ms
+
+mydb=# select * from column_t limit 10;
+ id | col1 | col2 | create_time
+----+----------+------+-------------------------------
+ 1 | a745d77b | .33 | 2020-10-26 14:28:20.633253+08
+ 2 | 4b6df494 | .42 | 2020-10-26 14:28:20.633253+08
+ 3 | 76fed9c1 | .73 | 2020-10-26 14:28:20.633253+08
+ 4 | 70c9664d | .74 | 2020-10-26 14:28:20.633253+08
+ 5 | 3384de8a | .48 | 2020-10-26 14:28:20.633253+08
+ 6 | 4158f3bf | .59 | 2020-10-26 14:28:20.633253+08
+ 7 | 5d1c3b9f | .63 | 2020-10-26 14:28:20.633253+08
+ 8 | 341876bb | .97 | 2020-10-26 14:28:20.633253+08
+ 9 | f396f4ed | .73 | 2020-10-26 14:28:20.633253+08
+ 10 | abfd78bb | .30 | 2020-10-26 14:28:20.633253+08
+(10 rows)
+
+Time: 9.982 ms
+```
+
+update
+
+```
+---
+---直接更新一个字段,列存比行存快近7倍
+---
+mydb=# update test_t set col1=col1;
+UPDATE 1000000
+Time: 19779.978 ms
+mydb=# update column_t set col1=col1;
+UPDATE 1000000
+Time: 2702.339 ms
+```
+
+## 结论
+
+1. 列存表比行存表在磁盘空间占用上节省近6倍。
+2. 查询指定字段,列存表比行存表快约20-35倍。
+3. select \* 的方式,列存表比行存表慢30%。
+4. 默认压缩方式批量导入数据,列存表比行存表快40%。
+
+
diff --git a/content/zh/post/gaoyunlong/title/title.PNG b/content/zh/post/gaoyunlong/title/title.PNG
new file mode 100644
index 0000000000000000000000000000000000000000..912319f07cad56d38dd41efe4125c4959c0da394
GIT binary patch
literal 148750
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