暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

Oracle 与 Clickhouse 数据存储方式趣味验证

490

介绍

关于数据库的使用场景,常用的分为OLTP和OLAP 2种,OLTP型数据库以行存为主,OLAP型数据库大多以列存为主,那么如何从数据库方面验证具体的存储方式,本文利用Oracle与 Clickhouse数据库,通过几个小方法进行验证,纯属娱乐。

最近项目需要,了解了一下Clickhouse,其实早就听说过此数据库,印象也是停留在这是一款分析型列存数据库,适合OLAP业务场景,看官方文档第一节,更加清晰的认识了一下。

行存和列存存储方式

所谓行存,在数据库底层以行为单位存储,一行的各个字段大概率在一个数据块,形式如下:

Row WatchID JavaEnable Title GoodEvent EventTime
#0 89354350662 1 Investor Relations 1 2016-05-18 05:19:20
#1 90329509958 0 Contact us 1 2016-05-18 08:10:20
#2 89953706054 1 Mission 1 2016-05-18 07:38:00
#N

处于同一行中的数据总是被物理的存储在一起。

常见的行式数据库系统有:Oracle 、 Mysql 、pg等。

所谓列存,在数据库底层以列为单位存储,同一字段的不同行大概率在一个数据块,形式如下:

Row: #0 #1 #2 #N
WatchID: 89354350662 90329509958 89953706054
JavaEnable: 1 0 1
Title: Investor Relations Contact us Mission
GoodEvent: 1 1 1
EventTime: 2016-05-18 05:19:20 2016-05-18 08:10:20 2016-05-18 07:38:00

行存和列存读取方式

既然行存和列存 存储方式不同,进行查询分析时,方式自然也不同。

行式,假如需要读取表中的3个字段,形式如下:

在没有索引加持的情况下,会读取整行数据,然后筛选所需的3个字段记录。

行存.gif

列式,假如需要读取表中的3个字段,形式如下:
按列读取数据,直接读取3个字段,读取的数据块大大降低。
列存.gif

存储验证方式

方式一 数据库元数据信息

Oracle 元数据表 dba_segments 可以方便的查到整个表的大小,但没有元数据表可以查到具体字段的大小。


SQL> select sum(bytes)/1024/1024/1024 from dba_segments where segment_name='T_PART_GLOBAL_PSDDU';

SUM(BYTES)/1024/1024/1024
-------------------------
                  .390625

Clickhouse 元数据表system.parts查询整个表,system.parts_columns查询表每个字段大小。

微信截图_20241129134253.png

微信截图_20241129134324.png

小结:从Oracle 和 Clickhouse 元数据表可以看出,Oracle 无法统计每个字段占用的大小,而Clickhouse 由于列存的原因,可以详细的统计每个字段大小。

方式二 查询时间

Oracle 通过查询不同字段的方式,进行验证,通过查看表T_OBJ的OBJECT_ID和OBJECT_NAME 字段,时间分别为1.17s和1.21s,相差不多,个人认为都是在通过全表扫描统计数据吧。

SQL> ALTER SYSTEM FLUSH BUFFER_CACHE;

System altered.

Elapsed: 00:00:00.06
SQL> select count(OBJECT_ID) from (select OBJECT_ID from T_OBJ);

COUNT(OBJECT_ID)
----------------
        11187328

Elapsed: 00:00:01.17
SQL> ALTER SYSTEM FLUSH BUFFER_CACHE;

System altered.

Elapsed: 00:00:00.07
SQL> select count(OBJECT_NAME) from (select OBJECT_NAME from T_OBJ);

COUNT(OBJECT_NAME)
------------------
          11187584

Elapsed: 00:00:01.21

Clickhouse 通过查询不同字段的方式,进行验证,查看表srv_log的message和business字段,时间分别为1.69s和0.3s差异较大。CK不仅显示了查询时间,更显示了查询数据量。
微信截图_20241129151242.png

小结:通过进行实际表的不同字段查询,在Oracle和Ck的表现来看,Oracle 查询不同字段时间差别不大,CK查询不同字段查询时间相差较大,也从侧面验证了CK 是进行列存的。

方式三 查询数据量

Oracle 通过查询不同字段的方式,进行验证,查询表T_OBJ的字段OBJECT_ID和OBJECT_NAME,显示查询数据块数量一致,而且执行计划也显示在进行全表扫描。

SQL> set autot on
SQL> ALTER SYSTEM FLUSH BUFFER_CACHE;

System altered.

Elapsed: 00:00:00.05
SQL> select count(OBJECT_ID) from (select OBJECT_ID from T_OBJ);

COUNT(OBJECT_ID)
----------------
        11187328

Elapsed: 00:00:01.31

Execution Plan
----------------------------------------------------------
Plan hash value: 3371328957

----------------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |     1 |     5 |  1375   (1)| 00:00:17 |
|   1 |  SORT AGGREGATE    |       |     1 |     5 |            |          |
|   2 |   TABLE ACCESS FULL| T_OBJ |   349K|  1707K|  1375   (1)| 00:00:17 |
----------------------------------------------------------------------------


Statistics
----------------------------------------------------------
         22  recursive calls
         18  db block gets
     159427  consistent gets
     159405  physical reads   <==============  物理读,数据块数
        908  redo size
        537  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL> ALTER SYSTEM FLUSH BUFFER_CACHE;

System altered.

Elapsed: 00:00:00.05
SQL> select count(OBJECT_NAME) from (select OBJECT_NAME from T_OBJ);

COUNT(OBJECT_NAME)
------------------
          11187584

Elapsed: 00:00:01.32

Execution Plan
----------------------------------------------------------
Plan hash value: 3371328957

----------------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |     1 |    25 |  1375   (1)| 00:00:17 |
|   1 |  SORT AGGREGATE    |       |     1 |    25 |            |          |
|   2 |   TABLE ACCESS FULL| T_OBJ |   349K|  8535K|  1375   (1)| 00:00:17 |
----------------------------------------------------------------------------


Statistics
----------------------------------------------------------
         22  recursive calls
         15  db block gets
     159426  consistent gets
     159403  physical reads   <==============  物理读,数据块数
        876  redo size
        539  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

Clickhouse 通过查询不同字段的方式,进行验证,查询表SRV_LOG的字段message和business,显示查询数据量为26.G和8.9G,差异较大,而且都没有达到表的最大数据量70.4G,可以说明是按列查询。
注:user 条件基本可以查到表的所有数据。
微信截图_20241129151242.png

微信截图_20241129153153.png

小结:通过进行实际表的不同字段查询,在Oracle和Ck的表现来看,Oracle 查询数据量一样,CK查询相差较大,且都为达到表的数据量,也从侧面验证了CK 是进行列存的。

方式四 查询具体数据存储

Oracle 通过BBED或者dump的方式可以看到具体块存储的内容,下面通过dump方式查看,可以看到block_row_dump中,每行数据都在一起存储。

SQL> col OBJECT_NAME for a30
SQL> select object_name,dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(rowid) from T_OBJ where rownum<10;

OBJECT_NAME                    DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
------------------------------ ------------------------------------ ------------------------------------
ICOL$                                                             4                                 3635
I_USER1                                                           4                                 3635
CON$                                                              4                                 3635
UNDO$                                                             4                                 3635
C_COBJ#                                                           4                                 3635
I_OBJ#                                                            4                                 3635
PROXY_ROLE_DATA$                                                  4                                 3635
I_IND1                                                            4                                 3635
I_CDEF2                                                           4                                 3635

9 rows selected.

Elapsed: 00:00:00.00
SQL> alter system dump datafile 4  block  3635;

System altered.

--- first_ora_32571.trc
.......
block_row_dump:
tab 0, row 0, @0x1f33
tl: 77 fb: --H-FL-- lb: 0x0  cc: 14
col  0: [ 3]  53 59 53
col  1: [ 5]  49 43 4f 4c 24
col  2: *NULL*
col  3: [ 2]  c1 15
col  4: [ 2]  c1 03
col  5: [ 5]  54 41 42 4c 45
col  6: [ 7]  78 71 08 18 0c 26 24
col  7: [ 7]  78 71 08 18 0c 30 26
col  8: [19]  32 30 31 33 2d 30 38 2d 32 34 3a 31 31 3a 33 37 3a 33 35
col  9: [ 5]  56 41 4c 49 44
col 10: [ 1]  4e
col 11: [ 1]  4e
col 12: [ 1]  4e
col 13: [ 2]  c1 02
tab 0, row 1, @0x1ee4
tl: 79 fb: --H-FL-- lb: 0x0  cc: 14
col  0: [ 3]  53 59 53
col  1: [ 7]  49 5f 55 53 45 52 31
col  2: *NULL*
col  3: [ 2]  c1 2f
col  4: [ 2]  c1 2f
col  5: [ 5]  49 4e 44 45 58
col  6: [ 7]  78 71 08 18 0c 26 24
col  7: [ 7]  78 71 08 18 0c 26 24
col  8: [19]  32 30 31 33 2d 30 38 2d 32 34 3a 31 31 3a 33 37 3a 33 35
col  9: [ 5]  56 41 4c 49 44
col 10: [ 1]  4e
col 11: [ 1]  4e
col 12: [ 1]  4e
col 13: [ 2]  c1 05
tab 0, row 2, @0x1e98
tl: 76 fb: --H-FL-- lb: 0x0  cc: 14

Clickhouse 通过查看其存储文件的方式可以看到,每一列数据都有一个xxx.bin文件,也证明确实按列存储。
xxx.bin内容暂未学习到有何方法可以具体查看到。

微信截图_20241129155620.png

小结:通过查看表数据的实际存储,在Oracle 按行存储,在数据块中可以看到每行数据紧密排列,Clickhouse 在存储文件的方式上已经把每个字段隔离开来。

总结

通过以上4种方式,对OLTP和OLAP 2种数据库系统的存储方式上进行验证学习。当然,2种类型的数据库发展这么长久,行存、列存的方式肯定是事实存在,验证并不是代表质疑,一种学习方式,更好的了解一款数据库。

参考文档

官方文档https://clickhouse.com/docs/zh

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论