写点什么

YashanDB 表介绍

作者:YashanDB
  • 2025-02-18
    广东
  • 本文字数:6361 字

    阅读完需:约 21 分钟

本文内容来自 YashanDB 官网,原文内容请见 https://doc.yashandb.com/yashandb/23.3/zh/%E6%A6%82%E5%BF%B5%E6%89%8B%E5%86%8C/%E5%85%B3%E7%B3%BB%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/%E6%A8%A1%E5%BC%8F%E5%AF%B9%E8%B1%A1/%E8%A1%A8.html


在关系型数据库中一个表就是一个关系(Relation),一个关系数据库可以包含多个表。表是一种按行、列排列的具有相关信息的逻辑结构,是关系数据库中组织数据的基本单元。

表的元素


# 列

数据库中表包含若干个列(或字段),列表示关系模型的属性,每个列描述了它所包含的数据的意义。例如一个字节的数据 0x61,当它是一个一字节整型列的数据时表示数值97,当它是一个字符型列的数据时表示字符a


每个列的定义通常包含列名、数据类型、列最大长度等。对于变长的数据类型,通常需要显式声明列的最大长度,定长数据类型,通常不需要显式指定最大长度。


创建表时声明的列,通常具备以下特征:


  • 数据库会存储该列的数据,占用一定的存储空间。

  • 查询表的数据时,会显示该列的数据。


但是 YashanDB 中还包存在以下三种特殊列不满足上述特征:


  • 虚拟列:其数据不占用存储空间,只在需要访问该列的数据时,通过该列的 default 表达式计算出该列的值。

  • 例如,通过以下语句为表创建函数索引:


    CREATE TABLE employee(id INT, name VARCHAR(32));        CREATE INDEX idx_emp_name ON employee(UPPER(name));
复制代码


Copied!
索引idx\_emp\_name并非基于employee表的列而创建,而是基于upper(name),在此情况下,数据库会为employee表添加一个虚拟列,该列的default值为upper(name)。
复制代码


  • 隐藏列:其数据会占用存储空间,但用户无法直接查询隐藏列的数据。

  • 例如,用户创建的表中包含一个自定义的对象类型,对象类型可能包含若干个属性,每个属性会在表中以至少一个隐藏列存储,用户无法直接查询这些隐藏列,只能通过查询对象列,再通过访问对象类型的属性。


    CREATE OR replace TYPE person AS object (id CHAR(18), name VARCHAR(32), birthday DATE);    /    CREATE TABLE employee(emp_id INT, personal_info person);    INSERT INTO employee VALUES(1, person('11011120000101011X', 'Zhang San', '2000-01-01'));            SELECT column_id, column_name, data_type FROM USER_TAB_COLUMNS WHERE table_name = 'EMPLOYEE' ORDER BY 1;           COLUMN_ID COLUMN_NAME                                                      DATA_TYPE                                                                         0 EMP_ID                                                           INTEGER                                                                      1 PERSONAL_INFO                                                    PERSON                                                      PERSON                                                                SELECT column_id, column_name, data_type FROM USER_TAB_COLS WHERE table_name = 'EMPLOYEE' ORDER BY 1;           COLUMN_ID COLUMN_NAME                                                      DATA_TYPE                                                                         0 EMP_ID                                                           INTEGER                                                                      1 PERSONAL_INFO                                                    PERSON                                                                       2 SYS_NC00002$                                                     CHAR                                                                         3 SYS_NC00003$                                                     VARCHAR                                                                      4 SYS_NC00004$                                                     DATE           SELECT e.personal_info.name FROM employee e;        PERSONAL_INFO.NAME                        Zhang San                        
复制代码


Copied!
在上述示例中,employee表包含一个personal\_info列,该列为用户自定义的person数据类型,该类型包含id、name、birthday三个属性,这三个属性不会显示在USER\_TAB\_COLUMNS视图中,因此无法直接访问。
复制代码


  • 已删除的列:无法被访问。

  • 当用户通过 alter table 语句删除掉表中某一列后,该列的定义并不会从系统表中删除,而是仅将该列标记为删除,其数据也不会从存储空间中删除。

# 行

表中的一行,即为关系模型中的一个元组(或记录)。它由一组表的列数据组成。表中的一行代表该表中存储的某一个特定实体(或对象)的所有属性信息。

# 数据类型

表中的每一列都必须指定一个数据类型及规格,当用户向表中插入数据时,待插入的数据将被强制按照列的数据类型和规格做转换。其中,规格包括列的最大长度、精度等信息(非必须项)。


YashanDB 内置了常用的基础类型,包括字符型、数值型以及日期时间型。

# 字符型

VARCHAR 类型


VARCHAR 类型用于存储变长的字符串。


用户如果将表中的某一列数据类型指定为 VARCHAR 类型,需要同时指定该列的最大长度(字符或字节)。语法示例如下:



VARCHAR(10)
VARCHAR(10 byte)
VARCHAR(10 char)
复制代码


Copied!


当用户向表中插入的字符串时,SQL 语句中字符串需要用单引号包裹,且根据字符串长度不同而有不同表现:


  • 字符串长度超过该列的最大长度时,会返回错误。

  • 字符串长度小于该列的最大长度时,按实际输入的字符串进行存储。


CHAR 类型


CHAR 类型用于存储定长的字符串,用户可以指定最大长度(字符或字节)。


当用户向表中插入的字符串时,SQL 语句中字符串需要用单引号包裹,且根据字符串长度不同而有不同表现:


  • 字符串长度超过该列的最大长度时,会返回错误。

  • 字符串长度小于该列的最大长度时,将在字符串末尾填充若干空格,直到字符串长度等于最大长度。


由于 CHAR 类型存在空格补位机制(实际存储的数据会填充至最大长度),因此在数据更新时,长度始终保持一致,其性能在某些场景下会优于 VARCHAR 类型,但其消耗的存储空间会相对比 VARCHAR 类型更大。


两个 CHAR 类型的值在比较大小时,将忽略末尾补位的空格。


CHAR 类型与 VARCHAR 类型比较大小时,CHAR 类型末尾补位的空格仍会参与比较。


NCHAR 与 NVARCHAR 类型


NCHAR 用于指定支持 UNICODE 的固定长度字符串,NVARCHAR 用于指定支持 UNICODE 的可变长度字符串,这两种字符型仅支持在配置 UNICODE 字符集的数据库中使用,可以对多语言数据进行存储。


当使用这两种类型时,类型的长度仅指字符长度。

# 数值型

NUMBER 类型


YashanDB 的 NUMBER 类型可以存储定点数和浮点数。使用 NUMBER 类型时,可以指定精度和范围,格式如下:


NUMBER(precision, scale)
复制代码


Copied!


precision 和 scale 的含义如下:


  • precision 表示数字的最大位数。用户输入的数值将按照 precision 做四舍五入,以确保结果的数字位数不超过 precision。

  • scale 表示小数点到最后一位有效数字之间的数字位数,如果 scale 为正数,则 scale 表示小数点后的数字位数;如果 scale 为负数,则表示整数部分最后一位有效数字后有多少个 0,此时无小数部分。例如,123 按NUMBER(5,2)存储为 12300E-2,按NUMBER(5,-2)存储为 1E2。


NUMBER 类型存储格式的编码与硬件和操作系统无关,为 YashanDB 内部编码格式,可跨平台迁移。


NUMBER 类型的有效数字最大可支持 38 位。


原生数值类型


原生数值类型指该类型的编码方式与 CPU 支持的数值类型一致,包括原生的整数类型和浮点数类型。


  • 原生整数类型:YashanDB 支持四种整数类型,其存储格式均采用 CPU 架构支持的原生格式,因此运算性能较好,但存储格式与 CPU 的字节序相关,无法保持跨平台兼容。



  • 原生浮点数类型:YashanDB 支持以下两种浮点数,BINARY_FLOAT 与 BINARY_DOUBLE 分别对应 ANSI/IEEE Std 754-1985 标准定义的单精度浮点数和双精度浮点数。



原生类型与 NUMBER 类型的差异


  • 相对于原生整数类型而言,NUMBER 支持的数值范围和有效数字位数更大。

  • NUMBER 类型采用变长方式存储有效数字,在数值远小于原生整数类型的边界时,通常 NUMBER 占用的存储空间更小。

  • 相对于原生浮点数类型而言,NUMBER 类型最大支持 38 位有效数字,比原生浮点数类型结果更精确。

  • 原生类型的四则运算可以直接调用 CPU 指令,因此性能更好。

# 日期时间型

日期时间类型


表示某个日期或时刻,具体包括日期(DATE)、时间(TIME)、时间戳(TIMESTAMP)三个数据类型。这三种类型在数据库中存储的是从某个特定时间开始的时间间隔数值,因此,日期、时间类型可以进行加、减运算。


用户也可以将日期、时间以某种格式转化成字符串显示。


时间间隔类型


表示两个日期或时刻之间的间隔长度,具体包括年到月间隔(INTERVAL YEAR TO MONTH)、天到秒(INTERVAL DAY TO SECOND)两个数据类型。

# 大对象型

某些数据的长度上限可能很大(超过一个数据块的大小),在数据库中会占用大量的存储空间。如果 YashanDB 将这种数据像其他字符或二进制数据类型一样存储,则每行数据可能占用大量的数据块,即使用户不查询该列数据,数据库在扫描该表时,仍然会访问大量的数据块,影响用户请求的响应速度。因此,YashanDB 提供了一组大对象数据(LOB,Large Object)类型,包括 CLOB(Character Large Object)、BLOB(Binary Large Object)和 NCLOB(National Character Large Object)三种类型。


YashanDB 只会将长度较小的 LOB 数据与行内其他列数据一起存储,长度较大的大对象类型数据只在行内存储一个 LOB 数据的位置信息,而实际数据则单独存储在其他数据块中,因此 LOB 数据在行内只占用极少的空间。


当用户扫描包含 LOB 类型的表时,并不会扫描 LOB 数据所在的数据块;当用户需要访问 LOB 数据时,需要从行内取到 LOB 数据的位置信息,然后再定位到 LOB 数据所在的数据块。因此,当一个表中包含大量较长的 LOB 数据时,如果用户的 SQL 语句中不涉及 LOB 列的访问,那么该 SQL 语句执行的性能不会因为 LOB 数据的存在而受到明显地影响,但是当用户需要访问 LOB 列的数据时,数据读取的性能会比其他数据类型数据的读取差。

# 其他数据类型

ROWID


当表中的数据按行组织时,系统根据每一行数据所在物理地址信息生成一个全局唯一记录,即 ROWID。ROWID 用于检索表数据时的寻址,也可以用作每一行数据的唯一标识。


RAW


变长的二进制类型。


BIT


BIT 类型支持 1-64 位宽度(Size)的二进制位图,每 BIT 位只允许存放 0/1 值。


布尔型


布尔型数据的值只有 1(TRUE)和 0(FALSE),其字节长度为 1,可用于指示某个二元特性的状态。


JSON


YashanDB 中的 JSON 类型是一种可变长度数据类型,通过解析符合标准 JSON 格式的字符串获得的二进制数据。

表的组织方式



表的数据相当于一个二维矩阵,存储表的数据时,可以按行存储,即将一行的所有列数据集中存储,存完一行,再存储下一行;也可以按列存储,即先存一列的所有行数据,存完一列之后,再存下一列。

# 行存表

建表时将表的组织方式指定为 HEAP,则表的数据将按行的方式组织。表的每一行数据将按表定义中列的顺序存储。行存表适用于数据按行获取的场景,因此通常用于事务型业务场景。


例如 employees 表数据如下表所示:



则数据的组织方式为:


row1: 1, Zhang San, marketing; row2: 2, Li Si, sales; row3: 3, Wang wu, support
复制代码


Copied!

# 列存表

列存表的特点是每列的数据集中存储,数据按列查询速度远大于按行读取,适用于分析型的场景。分析型场景中,有大量数据是不需要更新的,业务只会对数据做查询,这部分数据称为稳态数据,通常可以对这些数据做进一步处理(压缩、排序等),以提高查询性能。少数需要更新的数据,称为实时数据。

# LSC 表

建表时,可将表的组织方式指定为 LSC。LSC 表适用于海量稳态数据分析场景,每个列的数据集中存储。LSC 表将数据分为实时数据区和稳态数据区。数据写入数据库时,先写入实时数据区,实时数据区的数据使用 segment 存储,以适应业务写入的随机性。当数据逐步稳定后,则将数据转入稳态数据区,稳态数据采用大颗粒度、高压缩比的对象存储,通过数据排序、稀疏索引等方式,实现查询的加速。

# TAC 表

建表时,可将表的组织方式指定为 TAC。TAC 是一种面向数据实时分析的列存表,TAC 表的数据存储在实时数据区,每个列的数据集中存储。由于数据在实时数据区,因此数据的更新性能优于 LSC 表。

特殊表类型



特殊表类型是指除普通表以外的临时表和外部表。

# 临时表

临时表用于存储仅在事务或会话期间存在的会话私有数据,不同会话间该类数据不共享。

# 临时表的分类

临时表按照表的定义是否在不同会话间共享分为全局临时表(Global temporary table)和私有临时表(Private temporary table)。


全局临时表按照事务结束时是否保留数据分为事务级全局临时表(on commit delete rows)和会话级全局临时表(on commit preserve rows)。


私有临时表按照事务结束时是否保留表定义及数据分为事务级私有临时表(on commit drop definition)和会话级私有临时表(on commit preserve definition)。


下表展示不同类型的临时表的行为差异:


# 临时表数据的存储

当一个会话向临时表中插入数据时,数据库系统会在临时表空间为该临时表创建 segment,并分配数据块,该会话再次查询该临时表时,数据库将从 segment 上获取数据,但是该 segment 对于其他会话是不可见的。事务级全局/私有临时表在事务结束时会将 segment 所占有空间释放,会话级全局/私有临时表在会话结束时会将 segment 所占的空间释放。


全局临时表的定义是持久化到系统表中的,除非用户执行删除表的操作将该表定义删除,否则,不会因事务结束、会话结束、进程重启等导致全局临时表的定义丢失。私有临时表的定义是存储在内存中的,事务级私有临时表会在事务结束时从内存中清除该表的定义,会话级私有临时表则会在会话结束时清除该表的定义。

# 外部表

外部表指数据存储在数据库外部的数据表,其存储空间不受数据库进程管理,数据库仅存储表的定义等元数据信息,以便数据库可以像访问普通表一样访问外部表。

# 外部表的意义

外部表在导入数据库时,只需向数据库写入外部表的元数据,实际数据不会占用数据库的存储空间,因此在数据仓库等场景下,可大大减少数据入库的时间和存储空间消耗。


外部表的数据实际存储的位置可以灵活多样,例如文件系统、云存储、分布式文件系统等。

# 外部表数据访问

数据库访问外部表数据是通过数据库对应的外部表驱动实现的,外部表数据访问驱动可以解析外部表文件中的数据,从而实现像访问普通表一样访问外部表文件中的数据。


YashanDB 目前仅支持 CSV 格式的外部表数据访问驱动。

# 外部表的创建

创建外部表的语法如下:


CREATE TABLE ...ORGANIZATION (HEAP | TAC | LSC | EXTERNAL [external_table_clause])
external_table_clause=([TYPE access_driver_type] [external_table_data_props]) [REJECT LIMIT (integer | UNLIMITED)]
external_table_data_props=[DEFAULT DIRECTORY directory] [ACCESS PARAMETERS ( opaque_format_spec )] [LOCATION [directory :] ('location_specifier')]
复制代码


Copied!


创建表时,通过指定 ORGANIZATION EXTERNAL 来声明该表是外部表。同时需要指定 access_driver_type 来指定外部表的数据访问驱动,以及指定 LOCATION 来声明外部表文件的位置。


数据库在创建外部表时,仅将必要的元数据写入系统表,并不会存储外部表文件中的数据、数据组织方式等。另外,数据库会存储访问外部表文件的必要信息(例如数据访问驱动的类型、外部表对应的外部表文件位置等),以及将外部表文件中的数据以表的方式获取的方法(例如 CSV 文件中的列与外部表的列之间的映射关系)。

发布于: 刚刚阅读数: 4
用户头像

YashanDB

关注

全自研国产新型大数据管理系统 2022-02-15 加入

还未添加个人简介

评论

发布
暂无评论
YashanDB表介绍_数据库_YashanDB_InfoQ写作社区