keyedTable

语法

keyedTable(keyColumns, X, [X1], [X2], …..)

keyedTable(keyColumns, capacity:size, colNames, colTypes)

keyedTable(keyColumns, table)

参数

keyColumns 是一个字符串标量或向量,表示主键。

第一种用法中,X, X1….是向量。

第二种用法中,

capacity 是正整数,表示建表时系统为该表分配的内存(以记录数为单位)。当记录数超过 capacity 时,系统会首先会分配 capacity 1.2~2倍的新的内存空间,然后复制数据到新的内存空间,最后释放原来的内存。对于规模较大的表,此类操作的内存占用会很高。因此,建议建表时预先分配一个合理的 capacity

size 只能是0或1。若 size=0,则建立一个空表;若 size=1,则建立一个只包含1条记录的表,其中记录的初始值取决于列的数据类型:

  • BOOL 类型默认值为 false;

  • 数值类型、时间类型、IPADDR、COMPLEX、POINT 的默认值为 0;

  • Literal, INT128 类型的默认值为 NULL。

colNames 是字符串向量,表示列名。

colTypes 是向量,表示各列的数据类型。

第三种用法中,table 是一个表。注意,table 中的 keyColumns 不能包含重复值。

详情

创建键值内存表。一个键值内存表有一个主键。主键可由一个或多个字段组成。

向表中添加新记录时,系统会自动检查新记录的主键值,如果新记录的主键值与已有记录的主键值重复时,会更新表中对应的记录。

查询优化:

  1. 对于键值内存表,满足以下条件,SQL 查询性能会优于普通内存表:

  • SQL语句中只能使用 =, in 或 and, 且 in 谓词使用小于等于两次;

  • 查询语句必须包含 keyColumns 所有列。

  1. 查询 keyedTable 时,建议调用 sliceByKey 以提高性能。

  2. 请对比 索引内存表 优化 SQL 查询条件。

具体请参考例3。

注意:该函数不支持创建一个包含 array vector 类型的键值表。

例子

例1. 创建键值表

第一种写法:

$ sym=`A`B`C`D`E
$ id=5 4 3 2 1
$ val=52 64 25 48 71
$ t=keyedTable(`sym`id,sym,id,val)
$ t;

sym

id

val

A

5

52

B

4

64

C

3

25

D

2

48

E

1

71

第二种写法:

$ t=keyedTable(`sym`id,1:0,`sym`id`val,[SYMBOL,INT,INT])
$ insert into t values(`A`B`C`D`E,5 4 3 2 1,52 64 25 48 71);

第三种写法:

$ tmp=table(sym, id, val)
$ t=keyedTable(`sym`id, tmp);

创建键值内存分区表:

$ sym=`A`B`C`D`E
$ id=5 4 3 2 1
$ val=52 64 25 48 71
$ t=keyedTable(`sym`id,sym,id,val)
$ db=database("",VALUE,sym)
$ pt=db.createPartitionedTable(t,`pt,`sym).append!(t);

例2. 更新键值表

$ t=keyedTable(`sym,1:0,`sym`datetime`price`qty,[SYMBOL,DATETIME,DOUBLE,DOUBLE])
$ insert into t values(`APPL`IBM`GOOG,2018.06.08T12:30:00 2018.06.08T12:30:00 2018.06.08T12:30:00,50.3 45.6 58.0,5200 4800 7800)
$ t;

sym

datetime

price

qty

APPL

2018.06.08T12:30:00

50.3

5200

IBM

2018.06.08T12:30:00

45.6

4800

GOOG

2018.06.08T12:30:00

58

7800

插入新记录,并且新记录中的主键值与表中主键值重复:

$ insert into t values(`APPL`IBM`GOOG,2018.06.08T12:30:01 2018.06.08T12:30:01 2018.06.08T12:30:01,65.8 45.2 78.6,5800 8700 4600)
$ t;

sym

datetime

price

qty

APPL

2018.06.08T12:30:01

65.8

5800

IBM

2018.06.08T12:30:01

45.2

8700

GOOG

2018.06.08T12:30:01

78.6

4600

插入新记录,并且新记录中的主键值重复:

$ insert into t values(`MSFT`MSFT,2018.06.08T12:30:01 2018.06.08T12:30:01,45.7 56.9,3600 4500)
$ t;

sym

datetime

price

qty

APPL

2018.06.08T12:30:01

65.8

5800

IBM

2018.06.08T12:30:01

45.2

8700

GOOG

2018.06.08T12:30:01

78.6

4600

MSFT

2018.06.08T12:30:01

56.9

4500

主键不允许更新:

$ update t set sym="C_"+sym;
Can't update a key column.

例3. 查询键值内存表

当过滤条件不使用 or,包含所有 keyColumns,并且每个条件都使用了等值谓词(=)或in谓词,且in谓词数量不超过两个时,键值内存表的查询性能优于普通内存表。

以下例子将比较键值内存表和普通内存表的查询性能。首先,分别创建包含100万条记录的普通内存表 t 和键值内存表 kt

$ id=shuffle(1..1000000)
$ date=take(2012.06.01..2012.06.10, 1000000)
$ type=rand(9, 1000000)
$ val=rand(100.0, 1000000)
$ t=table(id, date, type, val)
$ kt=keyedTable(`id`date`type, id, date, type, val);

例3.1

$ timer(100) select * from t where id=500000, date=2012.06.01, type=0;
Time elapsed: 161.574 ms

$ timer(100) select * from kt where id=500000, date=2012.06.01, type=0;
Time elapsed: 1.483 ms

$ timer(100) sliceByKey(t1, (500000, 2012.06.01, 0))
Time elapsed: 0.705 ms

例3.2

$ timer(100) select * from t where id in [1, 500000], date in 2012.06.01..2012.06.05, type=5;
Time elapsed: 894.241 ms

$ timer(100) select * from kt where id in [1, 500000], date in 2012.06.01..2012.06.05, type=5;
Time elapsed: 2.322 ms

in 谓词数量超过两个时,键值内存表不会进行查询优化:

例3.3

$ timer(100) select * from t where id in [1, 500000], date in 2012.06.01..2012.06.05, type in 1..5;
Time elapsed: 801.347 ms

$ timer(100) select * from kt where id in [1, 500000], date in 2012.06.01..2012.06.05, type in 1..5;
Time elapsed: 834.184 ms

若过滤条件没有包括所有 keyColumns,键值内存表亦不会进行查询优化:

例3.4

$ timer(100) select * from t where id=500000, date in 2012.06.01..2012.06.05;
Time elapsed: 177.113 ms

$ timer(100) select * from kt where id=500000, date in 2012.06.01..2012.06.05;
Time elapsed: 163.265 ms

相关函数:indexedTable