创建数据库和表
创建数据库
使用 database 函数来创建新的数据库或获取已有数据库的句柄。
database函数的语法:
database(directory, [partitionType], [partitionScheme], [locations], [engine=’OLAP’], [atomic=’TRANS’])
若配置项 enableChunkGranularityConfig = true:
database(directory, [partitionType], [partitionScheme], [locations], [engine=’OLAP’], [atomic=’TRANS’], [chunkGranularity=’TABLE’])
directory 是保存数据库的目录的路径。如果需要创建分布式文件系统中的数据库,directory应该以“dfs://”开头。
partitionType 有六种类型:顺序分区(SEQ),范围分区(RANGE),哈希分区(HASH),数值分区(VALUE),列表分区(LIST)和组合分区(COMPO)。
partitionScheme 描述了分区是如何创建的。它通常是一个向量,在序列域是一个整型标量。分区方案的说明决定了分区类型。partitionScheme支持以下数据类型:CHAR, SHORT, INT, DATE, MONTH, TIME, MINUTE, SECOND, DATETIME和SYMBOL。
分区类型 |
分区符号 |
分区方案 |
---|---|---|
顺序分区 |
SEQ |
整型标量。表示分区的数量。 |
范围分区 |
RANGE |
向量。向量的任意两个相邻元素定义分区的范围。 |
哈希分区 |
HASH |
元组。第一个元素是分区列的数据类型,第二个元素是分区的数量。 |
值分区 |
VALUE |
向量。向量的每个元素定义了一个分区。 |
列表分区 |
LIST |
向量。向量的每个元素定义了一个分区。 |
组合分区 |
COMPO |
向量。向量的每个元素是一个数据库句柄。 |
locations 是元组,指定分区的位置。元组中元素的数量应该与partitionType和partitionScheme共同决定的分区数量相同。若要在多个节点上保存分区时, 可以使用分布式文件系统或使用locations参数指定每个分区在哪些节点。如果没有指定locations参数,所有分区属于当前节点。我们不能指定分层域的分区。
engine = ‘OLAP’ 固定参数,其值不可修改。只有2.00版本支持修改 engine 参数。
atomic 表示是否允许并发写入同一分区。可选值为‘TRANS’和‘CHUNK’,默认值为‘TRANS’。
设置为‘TRANS’,不允许并发写入同一个分区。此时能够保证写入事务的原子性,即进行并发写入时,若存在分区被其他事务锁定而出现写入冲突,则本次并发写入全部失败。
设置为‘CHUNK’,允许并发写入同一个分区。若并发写入时,某分区被其它事务锁定,系统不会直接放弃本次写入,而是会完成未冲突分区的数据写入,同时不断尝试继续写入冲突的分区,直到10秒后仍无法写入,才放弃写入。此配置因不能完全保证事务的原子性,可能出现部分分区写入成功而部分分区写入失败的情况,同时由于采用了重试机制,不能保证写入的效率。
chunkGranularity 是一个字符串,用于指定分区的粒度。可选值为:
‘TABLE’:表级分区,设置后支持同时写入同一分区的不同表。
‘DATABASE’:数据库级分区,设置后只支持同时写入不同分区。
注意:该参数只有在配置 enableChunkGranularityConfig = true 时启用。
数据库创建后,不可修改分区类型。分区方案一般亦不可修改,仅有的例外为使用 addValuePartitions 或 addRangePartitions 函数增加值分区或范围分区。
创建维度表
维度表是分布式数据库中没有分区的表,一般用于存储不频繁更新的小数据集。我们可以使用 createTable 函数来创建维度表。
$ db=database("dfs://db1",VALUE,1 2 3)
$ timestamp = [09:34:07,09:36:42,09:36:51,09:36:59,09:32:47,09:35:26,09:34:16,09:34:26,09:38:12]
$ sym = `C`MS`MS`MS`IBM`IBM`C`C`C
$ price= 49.6 29.46 29.52 30.02 174.97 175.23 50.76 50.32 51.29
$ qty = 2200 1900 2100 3200 6800 5400 1300 2500 8800
$ t = table(timestamp, sym, qty, price)
$ dt=db.createTable(t,`dt).append!(t)
$ select * from dt;
timestamp |
sym |
qty |
price |
---|---|---|---|
09:34:07 |
C |
2200 |
49.6 |
09:36:42 |
MS |
1900 |
29.46 |
09:36:51 |
MS |
2100 |
29.52 |
09:36:59 |
MS |
3200 |
30.02 |
09:32:47 |
IBM |
6800 |
174.97 |
09:35:26 |
IBM |
5400 |
175.23 |
09:34:16 |
C |
1300 |
50.76 |
09:34:26 |
C |
2500 |
50.32 |
09:38:12 |
C |
8800 |
51.29 |
创建分区表
使用 createPartitionedTable 函数来创建分区表。
createPartitionedTable 函数的语法:createPartitionedTable(dbHandle, table, tableName, [partitionColumns], [compressMethods])
创建分区表时,我们需要提供一个高阶表,系统会在数据库中创建一个与高阶表结构相同的分区表。createPartitionedTable 函数的第二个参数用于指定模板表。除了顺序分区以外,创建其他分区类型的分区表时必须指定partitionColumns,系统会根据partitionColumns来划分分区。
范围分区
$ n=1000000
$ ID=rand(10, n)
$ x=rand(1.0, n)
$ t=table(ID, x)
$ db=database("dfs://rangedb", RANGE, 0 5 10)
$ pt=db.createPartitionedTable(t, `pt, `ID)
$ pt.append!(t)
$ select count(x) from pt;
count_x |
---|
1000000 |
在上面的例子中,数据库”dfs://rangedb”有两个根据范围划定的分区:[0,5)和[5,10)。内存表 t 根据 ID 列的值,分别存入这两个分区中。
数据库的操作需要数据库的句柄。要获取数据库的句柄,使用 database 函数并且只指定数据库路径即可。例如,要获取数据库”dfs://rangedb”的句柄:
$ db=database("dfs://rangedb")
值分区
$ n=1000000
$ month=take(2000.01M..2016.12M, n)
$ x=rand(1.0, n)
$ t=table(month, x)
$ db=database("dfs://valuedb", VALUE, 2000.01M..2016.12M)
$ pt = db.createPartitionedTable(t, `pt, `month)
$ pt.append!(t)
$ select count(x) from pt;
count_x |
---|
1000000 |
上例创建的数据库 dfs://valuedb
一共有17*12=204个分区,每个分区对应2000年1月到2016年12月之间的每个月。
哈希分区
$ n=1000000
$ ID=rand(10, n)
$ x=rand(1.0, n)
$ t=table(ID, x)
$ db=database("dfs://hashdb", HASH, [INT, 2])
$ pt = db.createPartitionedTable(t, `pt, `ID)
$ pt.append!(t)
$ select count(x) from pt;
count_x |
---|
1000000 |
数据库 dfs://hashdb
根据ID列划分为两个分区。
列表分区
$ n=1000000
$ ticker = rand(`MSFT`GOOG`FB`ORCL`IBM,n);
$ x=rand(1.0, n)
$ t=table(ticker, x)
$ db=database("dfs://listdb", LIST, [`IBM`ORCL`MSFT, `GOOG`FB])
$ pt = db.createPartitionedTable(t, `pt, `ticker)
$ pt.append!(t)
$ select count(x) from pt;
count_x |
---|
1000000 |
数据库 dfs://listdb
包含两个分区,第一个分区包含3只股票,第二个分区包含2只股票。
组合分区
组合分区类型的数据库和表可以按照2-3个分区列来划分分区。
$ n=1000000
$ ID=rand(100, n)
$ dates=2017.08.07..2017.08.11
$ date=rand(dates, n)
$ x=rand(10.0, n)
$ t=table(ID, date, x)
$ dbDate = database(, VALUE, 2017.08.07..2017.08.11)
$ dbID = database(, RANGE, 0 50 100)
$ db = database("dfs://compodb", COMPO, [dbDate, dbID])
$ pt = db.createPartitionedTable(t, `pt, `date`ID)
$ pt.append!(t)
$ select count(x) from pt;
count_x |
---|
1000000 |
上面的例子中,数据库 dfs://compodb
包含两层分区,第一层按照日期分区,每天一个分区,第二层按照ID的范围划分成两个分区,因此数据库一共有5*2个分区。