内存计算
DolphinDB内置轻量级的内存计算引擎,非常适合性能要求高、并发较大的计算任务。DolphinDB提供了丰富的数据结构,用于内存计算。具体请参考 第2章:数据类型和形式。本节主要介绍DolphinDB各种表在内存计算中的应用。
会话
会话是一个容器。它具有唯一的ID并存储许多已经定义的对象,例如局部变量、共享变量等。创建新会话的方式有多种,如启动命令行窗口、XDB连接、 GUI连接或Web URL连接。会话中的所有变量对于其他会话是不可见的,除非使用语句share在会话之间显式共享变量。目前DolphinDB仅支持表共享。
不再使用会话时需要把它关闭,以便释放被会话占用的系统资源。这是非常重要的。如果需要关闭XDB会话,我们可以使用 close 命令或将连接变量设置为NULL;如果需要关闭GUI或Web会话,我们需要相应地关闭GUI窗口或浏览器窗口。
内存表
内存表的数据保存在内存中,写入和查询的速度很快,但是节点关闭后数据会丢失,一般用于保存临时数据。内存表分为未分区内存表和分区内存表。
table 函数创建的表都是未分区内存表。
$ sym = `C`MS`MS`MS`IBM`IBM`C`C`C$symbol
$ 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
$ 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]
$ t1 = table(timestamp, sym, qty, price);
未分区内存表的更多操作请参考 内存表。
使用分区内存表进行运算能充分发挥多核CPU并行计算的优势。创建分区内存表需要指定内存分区数据库。使用 database 函数,并且指定数据库的路径为空字符串,即””。下例创建了一个VALUE分区类型的内存数据库。
$ n=10000
$ month=take(2000.01M..2000.12M, n)
$ x=rand(1.0, n)
$ t=table(month, x)
$ db=database("", VALUE, 2000.01M..2000.12M)
$ pt = db.createPartitionedTable(t, `pt, `month)
$ pt.append!(t)
$ select * from pt;
可以使用undef函数来释放内存表。例如,释放上例创建的内存分区表:
$ undef(`pt);
DolphinDB内存计算的一大特点是,可以使用SQL对表以外的数据结构如标量、向量、集合、矩阵、字典进行操作,增加脚本语言的灵活性。下例中,股票价格保存在数据表quotes中,股票权重保存在字典weights中。使用一条SQL语句就可以直接根据数据表和字典的数据,计算股票组合的价值。
$ Symbol=take(`AAPL, 6) join take(`FB, 5)
$ Time=2019.02.27T09:45:01.000000000+[146, 278, 412, 445, 496, 789, 212, 556, 598, 712, 989]
$ Price=173.27 173.26 173.24 173.25 173.26 173.27 161.51 161.50 161.49 161.50 161.51
$ quotes=table(Symbol, Time, Price)
$ weights=dict(`AAPL`FB, 0.6 0.4)
$ ETF = select Symbol, Time, Price*weights[Symbol] as weightedPrice from quotes
$ select last(weightedPrice) from ETF pivot by Time, Symbol;
Time |
AAPL |
FB |
---|---|---|
2019.02.27T09:45:01.000000146 |
103.962 |
|
2019.02.27T09:45:01.000000212 |
64.604 |
|
2019.02.27T09:45:01.000000278 |
103.956 |
|
2019.02.27T09:45:01.000000412 |
103.944 |
|
2019.02.27T09:45:01.000000445 |
103.95 |
|
2019.02.27T09:45:01.000000496 |
103.956 |
|
2019.02.27T09:45:01.000000556 |
64.6 |
|
2019.02.27T09:45:01.000000598 |
64.596 |
|
2019.02.27T09:45:01.000000712 |
64.6 |
|
2019.02.27T09:45:01.000000789 |
103.962 |
|
2019.02.27T09:45:01.000000989 |
64.604 |
共享表
内存表只在当前会话可见,需要通过 share 函数共享,才能在其他会话中可见。共享表不能删除、修改记录,仅支持插入新记录和查询操作。
$ share t1 as sharedT1;
上面的例子中,把表t1共享为sharedT1。其他会话访问表sharedT1就可以访问到t1的内容。
undef函数可以删除一个共享表。
$ undef(sharedT1,SHARED)
多版本并发控制表(mvcc table)
针对内存中频繁并发读写但很少更新或删除记录的场景,DolphinDB提供了一种特殊的内存表:多版本并发控制表。多版本并发控制表通过日志记录每次操作,读写互不影响。多版本并发控制表还可以持久化到磁盘上,后续可以加载到内存中操作。
使用 mvccTable 函数创建多版本并发控制表:
$ n=5
$ syms=`IBM`C`MS`MSFT`JPM`ORCL`FB`GE
$ timestamp=09:30:00+rand(18000,n)
$ sym=rand(syms,n)
$ qty=100*(1+rand(100,n))
$ price=5.0+rand(100.0,n)
$ temp=table(timestamp,sym,qty,price)
$ t1= mvccTable(1:0,`timestamp`sym`qty`price,[TIMESTAMP,SYMBOL,INT,DOUBLE],"/home/DolphinDB/Data","t1")
$ t1.append!(temp);
上例中,多版本并发控制表t1会持久化到磁盘/home/DolphinDB/Data/t1目录。
使用 loadMvccTable 函数把多版本并发控制表加载到内存:
$ loadMvccTable("/home/DolphinDB/Data",t1);
timestamp |
sym |
qty |
price |
---|---|---|---|
1970.01.01T00:00:39.091 |
MSFT |
4500 |
99.808702 |
1970.01.01T00:00:35.293 |
FB |
3600 |
26.644715 |
1970.01.01T00:00:36.334 |
MSFT |
3800 |
66.754334 |
1970.01.01T00:00:40.362 |
ORCL |
4800 |
15.480288 |
1970.01.01T00:00:35.565 |
MSFT |
1700 |
23.107408 |