建库建表
创建数据库
创建数据库可以通过两种方式:
- 通过 SQL
语句:
其中关键字不区分大小写。更多关于使用 SQL 语句创建数据库和表的内容,参考:create。CREATE DATABASE "dfs://test" PARTITIONED BY VALUE(1..10),ENGINE="TSDB",ATOMIC="TRANS",CHUNKGRANULARITY="TABLE"
- 通过
database
函数:database("dfs://test", VALUE, 1..10,, "TSDB", "TRANS", "TABLE")
上述两条语句都创建了一个名为 dfs://test 的分布式数据库,前缀 dfs://
是分布式数据库的标识。
- 指定了分区类型为值分区,并设置了 1 到 10 共 10 个初始分区。
- 指定了存储引擎的类型为 TSDB。
- 指定了写入事务的原子性层级为 TRANS,即不允许并发写入同一个分区。
- 指定了分区粒度为 TABLE,即支持同时写入同一分区的不同表。
下面以 database
函数为例,对创建数据库进行详细介绍
database(directory, [partitionType], [partitionScheme], [locations],
[engine=’OLAP’], [atomic=’TRANS’], [chunkGranularity=’TABLE’])
-
directory 用于指示数据库的存储目录。
- 创建内存数据库,只需将 directory
设为空,可通过以下脚本实现:
db = database("", VALUE, 1..10)
- 创建分布式数据库,此参数需要以
dfs://
开头,并指定一个唯一的库名,可通过以下脚本实现:db = database("dfs://uniquedb", VALUE, 1..10)
注:- 采用单节点模式部署的 DolphinDB 也支持创建分布式数据库。
- 数据库的库名一经确定,不可更改。
- 数据库的库名必须具有唯一性,不允许与现有数据库同名。可通过 existsDatabase 或 getClusterDFSDatabases 在创建前查看是否存在同名数据库,也可在创建后验证是否创建成功。
- 创建内存数据库,只需将 directory
设为空,可通过以下脚本实现:
-
partitionType 用于指示数据库的分区类型,partitionScheme 用于指示创建的分区结构,DolphinDB 提供了五种分区方式:
- 值分区(VALUE),partitionScheme
指定一个向量,每个元素定义一个分区,例如常见的按天分区可以通过以下脚本实现:
db = database("dfs://valuedb", VALUE, 2023.01.01..2023.12.31)
- 范围分区(RANGE),partitionScheme
指定一个向量,相邻两个元素构成一个左闭右开的区间,每个区间定义一个分区,例如常用的按年分区可通过以下脚本实现:
db = database("dfs://rangedb", RANGE, date(2020.01M+12*1..10))
- 哈希分区(HASH),partitionScheme 指定一个长度为 2
的向量,第一个元素指定分区的数据类型,第二个元素指定分区数,例如常见的按照股票代码进行哈希分区可通过以下脚本实现:
db = database("dfs://hashdb", HASH, [SYMBOL,25])
- 列表分区(LIST),partitionScheme
指定一个元组,元组的每个元素是一个向量,定义一个分区,例如:
db = database("dfs://listdb", LIST, [`A`B`C, `D`E])
- 组合分区(COMPO),partitionScheme
指定一个向量,向量的每个元素是一个内存数据库的句柄,用于指示各级分区的分区类型,每级分区可以独立采用上述四种分区方式,最多为 3
级分区。组合分区在逻辑上是并列的,并不存在从属或优先级关系,例如常见的对按天分区和按照股票代码哈希分区进行组合分区,可以通过以下脚本实现:
db1 = database("", VALUE, 2020.01.01..2021.01.01) db2 = database("", HASH, [SYMBOL,25]) db = database("dfs://compodb", COMPO, [db1,db2])
注:- 数据库的分区方式一经确定,不可更改。
- 数据库的分区的概念是针对库的,即同一库下的所有表都是采用相同的分区方案。
- 分布式表的值分区(VALUE)后续允许增加分区;分布式表的范围分区(RANGE)允许向后增加分区;其他方式的分区结构,即 partitionScheme 一经确定,不可更改。所以用户在设置分区结构时应充分考量,可参考:数据分区。
- 值分区(VALUE),partitionScheme
指定一个向量,每个元素定义一个分区,例如常见的按天分区可以通过以下脚本实现:
-
engine 用于指定数据库采用的存储引擎,有 OLAP 存储引擎 和 TSDB 存储引擎 可供选择,默认采用 OLAP。其中,TSDB 存储引擎仅在 200 系列 server 中可用。
OLAP 引擎查询和计算整列或多列的性能优越,数据压缩率高,但不适于存储列数较多的表(建议列数不超过 100)。TSDB 的点查性能更优,且兼具优秀的整列计算性能,综合考虑,推荐用户使用 TSDB 存储引擎。
// 采用OLAP引擎 db = database("dfs//olap", VALUE, 1..10,, "OLAP") // 采用TSDB引擎 db = database("dfs://tsdb", VALUE, 1..10,, "TSDB)
注:- 使用 TSDB 引擎创建数据库时,应检查配置文件,确保配置项
dataSync=1
且TSDBCacheEngineSize>0
。单节点的配置文件为 dolphindb.cfg,普通集群的配置文件为 cluster.cfg,高可用集群的配置项须通过 Web 界面修改。 - 使用 TSDB 引擎创建数据库时,需要连接数据节点或计算节点创建,不能在控制节点创建。
- TSDB 引擎只可应用于分布式数据库,不可用于内存数据库和本地磁盘数据库。
- 一个数据库的存储引擎一经确定,后续不可修改。
- 使用 TSDB 引擎创建数据库时,应检查配置文件,确保配置项
-
atomic 用于设置写入事务的原子性层级,即,是否允许并发写入同一分区。可选值为 "TRANS" 和 "CHUNK",默认值为 "TRANS"。
- 设置为 "TRANS" 时,写入事务的原子性层级为事务,即一个事务写入多个分区时,若某个分区被其他写入事务锁定而出现写入冲突,则该事务的写入全部失败。因此,该设置下,不允许并发写入同一个分区。
- 设置为 "CHUNK" 时,写入事务的原子性层级为分区。若一个事务写入多个分区时,某分区被其它写入事务锁定而出现冲突,系统会完成其他分区的写入,同时对之前发生冲突的分区不断尝试写入,尝试数分钟后仍冲突才放弃。此设置下,允许并发写入同一个分区,但由于不能完全保证事务的原子性,可能出现部分分区写入成功而部分分区写入失败的情况。同时由于采用了重试机制,写入速度可能较慢。
-
chunkGranularity 用于指定分区的粒度。可选值为 "TABLE" 和 "DATABASE",默认值为 "TABLE"。
- "TABLE":表级分区,设置后支持同时写入同一分区的不同表。
- "DATABASE":数据库级分区,设置后只支持同时写入不同分区。
-
创建数据库前请确保用户已经登录。可通过函数 getCurrentSessionAndUser 查看,如果返回结果的第二个元素不是 guest,表示用户已经登录。默认的管理员 admin 的初始密码为 123456,用户可通过以下脚本登录:
login(`admin,`123456)
-
创建数据库只有具备 DB_OWNER 权限的用户才能执行。可通过 getUserAccess 查看当前用户是否具有该权限,如果没有,请联系管理员赋权。
创建表
创建内存表
常用的内存表有 table,keyedTable, indexedTable, streamTable, mvccTable 和分区内存表 (createPartitionedTable)等,这里以
table
为例进行介绍。
table
有两种用法:
-
table(X, [X1], [X2], ...)
,把多个向量、元组、矩阵或表组合成一个表,向量名、元组名即为列名,集成表中的各列,-
每列的长度必须一致
-
注意参数的类型只能是上述几种,尤其是在数据只有一行的情况,例如
u = [2] v = [3] t = table(u, v)
-
变量名是大小写敏感的,但是表的列名大小写不敏感,请注意建表时不能出现重复列名
-
如果需要指定列名,可以在列后增加
as <alias>
, 例如t = table([1,2,3] as id, ["x","y","z"] as sym)
-
如果要创建存在空列的表,需要为其指定数据类型,如下例当中的 data 列
t = table(`A as tag, now() as time, int(NULL) as data)
-
-
table(capacity:size, colNames, colTypes)
,其中 capacity 为建表时分配的内存(以记录数为单位),如果该参数设置很大,即使创建空表,也会占用大量内存。table(100:0, `col1`col2`col3`col4, [INT,INT,DOUBLE,STRING])
目前支持对内存表进行值分区、范围分区、哈希分区和列表分区,可使用 createPartitionedTable 创建分区内存表。
创建分区内存表与创建分布式分区表的方式相同,如下例所示:
db = database("",VALUE,1..5)
schemaTb = table(1:0, `id`sym`val, [INT,SYMBOL,DOUBLE])
t = db.createPartitionedTable(schemaTb, `mpt, `id)
有关更多参数细节,参考:分区表。
创建分布式表
分布式表包括维度表和分区表两种类型。首先介绍一下维度表和分区表创建时的一些共有特点:
-
创建分布式表时,需要为其指定一个表名。同一个数据库下,表名具有唯一性,不允许创建同名分布式表。可使用函数
existsTable
查看是否存在同名表,以及确认创建是否成功。 -
创建分布式表时,需要一个表作为模板,创建一个跟该表结构一致的分布式表。该表可以是空表,也可以包含数据,使用非空表也不会将其中的数据写入分布式表,仅用于提供表结构。
-
提供表结构的表不可是流数据表。
-
如果是现有的分布式表或流数据表,想要复用其结构,可以通过
schema
函数查询其表的列名和列的数据类型,快速创建,也可查询少部分数据赋值给一个新的表变量作为模板。以流数据表为例:// st 为一流数据表,有以下两种方式快速复用其结构 t1 = select top 3 * from st t2 = table(1:0,st.schema().colDefs.name,st.schema().colDefs.typeString)
维度表
维度表是分布式数据库中没有分区的表,一般用于存储不频繁更新的小数据集。可以使用 createDimensionTable
函数来创建维度表。
db = database("dfs://db1", VALUE, 1..5)
schemaTb = table(1:0,`id`sym`qty`price,[INT,SYMBOL,INT,DOUBLE])
t = db.createDimensionTable(schemaTb,`dt)
分区表
创建分区表的 createPartitionedTable 函数语法如下:
createPartitionedTable(dbHandle, table, tableName, partitionColumns,
compressMethods, sortColumns, keepDuplicates=ALL,
sortKeyMappingFunction)
-
partitionColumns 同分区内存表类似,创建分布式分区表时,需要指定分区列,分区列的数据类型必须与分区结构一致。分区列一经确定,无法修改。
下例中,数据库根据日期值进行分区,建表时应指定一列数据类型为 DATE 或可以转化为 DATE 的列(DATETIME 类型数据可经
date
函数转换为 DATE 类型)db = database("dfs://valuedb", VALUE, 2023.01.01..2023.12.31) schemaTb = table(1:0,`date`time`sym`price,[DATE,TIME,SYMBOL,DOUBLE]) t = db.createPartitionedTable(schemaTb,`pt,`date)
下例中,数据库使用了由值分区和哈希分区组成的组合分区,分区列应指定两列,分别对应两级分区,且数据类型匹配:
db1 = database("", VALUE, 2020.01.01..2021.01.01) db2 = database("", HASH, [SYMBOL,25]) db = database("dfs://compodb", COMPO, [db1,db2]) schemaTb = table(1:0,`date`time`sym`price,[DATE,TIME,SYMBOL,DOUBLE]) t = db.createPartitionedTable(schemaTb,`pt,`date`sym)
-
sortColumns,当前数据库使用 TSDB 存储引擎时,则必须指定此参数。
- sortColumns 如果只有一列,则数据会根据此列,在分区内进行分组;如果有n(n>1)列,则数据会根据前 n-1 列进行分组,这时在考虑是否使用参数 sortKeyMappingFunction 进行降维时,无需考虑最后一列。
-
keepDuplicates,如果指定当前去重策略为 LAST 和 FIRST,sortColumns 的数量不得小于 2。
- TSDB 引擎可以根据 sortColumns 和 keepDuplicates 对数据进行去重,但 sortColumns 的设置不可过于随意,因为数据存储时会根据 sortColumns 创建索引,查询也可通过索引提升效率,如果索引设置不合理,不仅会因存储大量索引而造成磁盘占用过多,也会导致查询缓慢。