内存计算

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