DolphinDB Catalog 使用教程

数据库目录(database catalog)作为数据库管理系统中的重要组成部分,用于组织和管理各种数据库对象。为了向用户提供更便捷、更标准、兼容性更强的数据库访问体验,同时能够更方便地与第三方软件进行集成,DolphinDB 在 3.00.0 版本中引入了 catalog 功能。用户可通过 catalog 统一管理 database 和 table 等数据库对象,并使用标准 SQL 的语法对其进行访问。本文将详细介绍 catalog 的基本概念、具体用法与相关权限等。

1 DolphinDB 中的数据库对象

在之前版本的 DolphinDB 中,我们使用 database 和 table 两级概念。database 实际上表示为分布式数据库的一个具体的分区机制。 它通过 dbUrl 进行区分,在创建时通过 database 函数指定一个全局唯一的 dbUrl,且创建后不能重命名。同一个数据库下的多个分布式表不仅使用同一个分区机制,而且在物理存储上实现了 co-location 的机制,关联时会比较高效。

//通过database函数创建了一个dbUrl为"dfs://db1"的database
database(directory="dfs://db1", partitionType=RANGE, partitionScheme=0 5 10)
//通过dbUrl的方式使用create语句创建表
create table "dfs://db1"."pt"(
     id INT,
     deviceId SYMBOL,
     date DATE[comment="time_col", compress="delta"],
     value DOUBLE,
     isFin BOOL
)
partitioned by ID
 
// select 查询 "dfs://db1" 下的表pt
select * from loadTable("dfs://db1", "pt")

当通过 SQL 语句需要对一张表进行操作时,必须通过 loadTable 函数来引用一张表。这个方法与标准 SQL 有所不同,在使用上造成了一些不便。更重要的是旧版本中的 database 概念,仅限于一种分区机制。当一个业务领域包含多个不同分区机制的表时,不得不将其分割成多个 database,这与传统的一个业务领域创建一个数据库的原则相违背。

基于这两个局限性,DolphinDB 在 3.0 版本中引入了 catalog 功能。当我们创建了一个新的 catalog 时,相当于创建了一个超级数据库(super database),它可以包含多个database。这样的做法,使得新版本可以完全兼容旧版本的概念和功能,方便统一管理不同的 database(如一个部门中的多个 database)。同时,catalog 功能也支持使用标准 SQL 的语法来操作 catalog 下的库和表。注意:该功能只支持分布式数据库。

在 DolphinDB 中,catalog 的具体概念包括:catalog, schema, table。下表将详细介绍这三层概念,及其与现有库表结构的映射关系。

三级层次映射概念说明
catalogsuper database用于包含多个 schema (database) 的集合一个 catalog 中可以包含不同分区方案的 schema
schemadatabase对应旧版本中通过 database 函数创建的的 database一个 schema 下的所有 table 使用同一种分区方案可以在某个 catalog 中创建新的 schema,或是将已存在的 database 加入 catalog 以统一管理。
tabletable当前所使用的表,如分区表、维度表等

2 创建和使用 catalog

本章将从创建、SQL 使用、运维三个阶段详细介绍 catalog 的使用。

注意:使用时请确保使用 3.00.0 及以上版本的 DolphinDB。相关说明请参阅文档 DolphinDB-部署

2.1 创建 catalog 和 schema

(1) 创建 catalog

使用 createCatalog 函数创建一个名为 trading 的 catalog。

createCatalog("trading")

catalog 的名称必须由大小写字母开头,且只能由大小写字母、数字、下划线(_)组成。如:catalog, catalog1, catalog_example, catalog1_example。使用 catalog 时可以大小写不敏感。

使用 USE CATALOG 语句,切换到该 catalog。执行该操作后,若不指定具体的 catalog 则默认优先使用当前的 catalog 即 trading

use catalog trading;

(2) 创建 schema

使用 create database 语句在 trading 中创建一个名为 stock、按照 VALUE 分区、存储引擎为 OLAP 的 schema。

create database stock partitioned by VALUE(1..10), engine='OLAP'

schema 的名称约束与 database 相同,必须由大小写字母开头,且只能由大小写字母、数字、下划线(_)组成,如:schema1 , schema1_example。且使用 schema 时可以大小写不敏感。

由于上一步中使用 use 指定了当前 catalog,所以上述语句中的 stock 等价为 trading.stock。如未使用 use 语句指定 catalog 却直接输入 schema 的名称,则会报错:”The catalog doesn't exist.“

在后续使用其他 SQL 语句时,如 create tableselect 等,都遵循上述查找规则。

如果想要将一个已存在的数据库插入到 catalog 中,可以使用 createSchema 函数。

下例中,通过 database 函数创建 *dfs://db1 *之后,再向 trading 中插入路径为 dfs://db1 名为 stock2 的 schema。

database(directory="dfs://db1", partitionType=RANGE, partitionScheme=0 5 10) //通过database函数创建的db1
createSchema("trading", "dfs://db1", "stock2") // 通过createSchema函数创建对应的schema

(3) 在 schema 创建表

在该 schema 中创建一张表:

create table stock.quote (
     id INT,
     date DATE[comment="time_col", compress="delta"],
     value DOUBLE,
 )
 partitioned by id

由于已设置当前 catalog,此处 stock.quote 等价为 trading.stock.quote

注意:如果想查看 catalog 以及 schena 的相关操作变动,可以从控制节点日志中寻找对应的 Audit Log。Audit Log 包含具体操作的 catalog,schema,操作者等信息。格式如下:

ACL Audit: function createSchema [catalog=trading,dbUrl=dfs://db1,schema=stock2], called by user [xxx]

2.2 在 SQL 中使用 catalog

向表中插入一些样本数据:id 列范围从 1 到 10,因为是分区列,所以会分为 10 个分区;date 列范围为 2023.01.01 到 2023.01.30;value 列为 10.0 以内的 100 个随机数。生成的总数据量为 100 行。

dbUrl = exec dbUrl from getSchemaByCatalog("trading") where schema = "stock"
data = table(take(1..10, 100) as id, take(2023.01.01..2023.01.30, 100) as date, rand(10.0, 100) as value)
loadTable(dbUrl[0], "quote").append!(data)

下表为目前已支持的 SQL 操作。

操作类型操作语句功能说明
DDLcreate创建数据库或数据表
DDLalter向已有的表中添加一列
DDLdrop删除数据库或数据表
DMLupdate更新数据表中的记录
DMLdelete删除表中的记录
DQLselect访问表中数据

以下给出部分使用示例:

例 1 返回满足指定条件的数据

select * from stock.quote where id = 1;

返回结果:

iddatevalue
12023.01.011.4114
12023.01.113.5046
12023.01.211.927
12023.01.010.7042
12023.01.115.5941
12023.01.219.3329
12023.01.012.4815
12023.01.111.1198
12023.01.219.5832
12023.01.014.0467

例 2 更新满足指定条件的数据

update stock.quote set value = -1.0 where id > 5;
select * from stock.quote where id > 5;

返回结果:

iddatevalue
52023.01.01-1.0000
52023.01.11-1.0000
52023.01.21-1.0000

例 3 删除满足指定条件的数据

delete from stock.quote where id < 2;
select * from stock.quote where id < 2;

返回结果为空表。

注意:如果脚本中存在一个与 schema 名相同的变量名时,使用该 schema 进行查询等操作可能失败,

例如,定义一个命名为 *stock *的变量,与 catalog *stock *歧义。在 DolphinDB Script 中将优先将其解析为变量名,所以执行如下 select 语句时会报错。

stock=1
select * from stock.quote where id = 1; //getMember method not supported

可使用 undef 函数取消该变量:

undef(`stock)

2.3 运维相关

(1) 查看默认 catalog

如果想要查看当前 session 默认的 catalog,可以使用 getCurrentCatalog 函数。

use catalog trading;
getCurrentCatalog() // => "trading"

use catalog trading2;
getCurrentCatalog() // => "trading2"

(2) 重命名 catalog 和 schema

可以使用 renameCatalogrenameSchema 函数对 catalog 或 schema 重命名。

例 1 将 trading 重命名为 trading2

renameCatalog("trading", "trading2") 
getAllCatalogs() // => ["trading2"]

例 2 将 trading 中的 stock 重命名为 stock1

renameSchema("trading", "stock", "stock1") 
exec schema from getSchemaByCatalog("trading") // => ["stock1"]

(3) 查看 catalog 中的数据库信息

在上面的例子中,我们使用 create database 语句在 catalog *trading *创建了一个 stock 的 schema:

use catalog trading;
create database stock partitioned by VALUE(1..10), engine='OLAP'

使用 create database 语句创建的 schema,其 *dbUrl *的默认格式为”dfs://{创建时间戳}”。可通过 getSchemaByCatalog 进行查看。

getSchemaByCatalog("trading")

返回结果:

schemadbUrl
stockdfs://trading_stock_1712077295373

注意,dbUrl 是全局唯一且不变的,即使 schema 或者 catalog 进行重命名操作,dbUrl 也不会变。

3 权限介绍

3.1 catalog 级别权限设置

下表为 catalog 级别的权限位。

权限说明
CATALOG_MANAGE用于 catalog 相关操作的管理,如添加 schema、删除、重命名 catalog 等操作
CATALOG_READ用于 catalog 下所有表的数据读取操作
CATALOG_WRITE用于 catalog 下所有表的数据写入操作,包括插入、更新、删除
CATALOG_INSERT用于 catalog 下所有表的数据插入操作
CATALOG_UPDATE用于 catalog 下所有表的数据更新操作
CATALOG_DELETE用于 catalog 下所有表的数据修改操作

例如有一个名称为 trading 的 catalog ,要为用户 Adam 设置该 catalog 下的只读权限:

grant("Adam", CATALOG_READ, "trading")

3.2 schema 级别权限设置

下表为 schema 级别的权限位。这些权限与之前的 DB 级别的权限设置等价。

权限对应的 DB 级别权限说明
SCHEMA_MANAGEDB_MANAGE用于 database 级别操作的权限管理,如删除某个 database 等
SCHEMAOBJ_CREATEDBOBJ_CREATE用于 database 下所有表的 add 类 DDL 操作,如加列、创建表操作等
SCHEMAOBJ_DELETEDBOBJ_DELETE用于database下所有表的 drop 类 DDL 操作,如删列、删除表操作等
SCHEMA_READDB_READ用于 database 下所有表的数据读取操作
SCHEMA_WRITEDB_WRITE用于 database 下所有表的数据写入操作,包括插入、更新、删除
SCHEMA_INSERTDB_WRITE用于 database 下所有表的数据更新操作
SCHEMA_UPDATEDB_UPDATE用于 database 下所有表的数据更新操作
SCHEMA_DELETEDB_DELETE用于 database 下所有表的数据删除操作

schema 相关操作的 obj 字符串格式为 catalog.schema

下例中,为用户 Adam 赋予 trading(catalog) 下的 stock(schema)中的所有表的只读权限。

grant("Adam", SCHEMA_READ, "trading.stock")

3.3 级别间权限计算

在增加了 catalog 级别的权限设置后,我们的权限级别变成了四级:全局(*)级别、catalog 级别、database (schema) 级别、table 级别。以读取表 (TABLE_READ) 权限为例,下面介绍三级权限的计算规则:

  1. 如果设置了全局的 deny 权限(deny * 操作),则权限为拒绝读取。
  2. 如果设置了 catalog 级别的 deny 权限(deny CATALOG_READ 操作),则权限为拒绝读取。
  3. 如果设置了 database (schema) 级别的 deny 权限(deny DB_READ 或 SCHEMA_READ 操作),则权限为拒绝读取。
  4. 如果设置了 table 级别的 deny 权限(deny TABLE_READ 操作),则权限为拒绝读取。
  5. 否则,与上述流程相同,按顺序查看全局、catalog、database、table 这4个级别中是否存在 grant 的权限设置。如果有,则权限为允许读取,否则说明该用户既没有 grant,也没有 deny 任何表读取权限,则最终权限为拒绝读取。

总结:按照 deny 优先原则,顺序查看四个级别是否存在 deny 权限,再查看这四个级别是否存在 grant 权限。

举例说明:假设我们已经存在数据库 dfs://db1,下面有一张表 *pt。*我们为用户 Adam 设置该表的 deny 读权限,代表该用户无法读取 pt 的内容:

deny(`Adam, TABLE_READ, "dfs://db1/pt")

假设用户 *Adam *赋予了 catalog *trading *的读取权限:

grant(`Adam, CATALOG_READ, "trading")

此时,如果将 *dfs://db1 *加入 catalog,那么该用户是否有表 *pt *的读权限?

createSchema("trading", "dfs://db1", "stock2")

按照上述的规则计算:用户拥有 catalog 级别的 grant 权限和 pt 的 deny 权限,按照规则4,用户仍然没有 pt 表的读权限,即遵循 deny 规则优先的原则。

但如果 dfs://db1 下又拥有了一张新表 pt2,则因为用户拥有 catalog 级别的 grant 权限,所以用户可以读 pt2。即该用户可以读取该 catalog 下任意表的权限,但 pt 除外。

4 全文总结

DolphinDB 的 catalog 功能通过 catalog, schema, table 这三层概念便捷地集中管理多种数据库对象。用户能够以 catalog.schema.table 的格式指定库表对象,同时通过标准 SQL 语法调用 create, update, select 等语句,亦或者进行其他数据库操作。该功能在显著增强 DolphinDB 兼容性的基础上,极大优化了用户的使用体验,同时更方便用户进行数据的工程化管理。在后续版本中,DolphinDB 将进一步扩展 catalog 功能,如使用 catalog 管理外部数据源的数据等。