序列化外键 table 如何在 kdb 内部工作

How serializing foreign keyed table works internally in kdb

我有一个使用外键链接到引用 table 的键控 table(引用 table),我使用集合运算符序列化两个 table。

q)kt:([sym:`GOOG`AMZN`FB]; px:20 30 40);
q)`:/Users/uts/db/kt set kt
q)t:([] sym:`kt?`GOOG`AMZN`FB; vol:5?10000)
q)`:/Users/uts/db/t set t

然后我从内存中删除这些table

q)delete kt,t from `.

现在我反序列化内存中的 table t:

t:get `:/Users/uts/db/t

如果我在此之后执行 meta t 它会失败,期望 kt 作为外键。 如果我打印 t,正如预期的那样,它会在 table t.

的 sym 列中显示索引值

那么,问题来了——

  1. 由于kdb在磁盘上存储了每个table(即c,t,f,a)的meta及其对应的值,那么tablet序列化在内部是如何工作的?

  2. 这些值如何(以二进制格式以何种形式)存储在文件 t 中。

    -rw-r--r-- 1 uts staff 100 Apr 13 23:09 t

tl;dr 外键存储为引用的键列的 4 字节索引向量 table 加上 [= 的名称59=]一个外键指的是.

据我所知,kx 从未记录过它们的文件格式,但我认为可以直接从 q 控制台会话中推断出一些与您的问题相关的有用信息。

让我稍微修改一下您的示例,使事情变得更简单。

q)show kt:([sym:`GOOG`AMZN`FB]; px:20 30 40)
sym | px
----| --
GOOG| 20
AMZN| 30
FB  | 40
q)show t:([] sym:`kt$`GOOG`GOOG`AMZN`FB`FB)
sym
----
GOOG
GOOG
AMZN
FB
FB

我只在 t 中留下了一栏 - sym - 因为 vol 与问题无关。我们先保存t没有任何数据

q)`:/tmp/t set 0#t
`:/tmp/t
q)hcount `:/tmp/t
30

现在我们知道空的时候需要30个字节来表示t。让我们看看当我们开始向 t:

添加行时是否存在模式
q){`:/tmp/t set x#t;`cnt`size!(x;hcount[`:/tmp/t] - 30)} each til[11], 100 1000 1000000
cnt     size
---------------
0       0
1       4
2       8
3       12
4       16
5       20
6       24
7       28
8       32
9       36
10      40
100     400
1000    4000
1000000 4000000

我们可以看到,添加一行会使 t 的大小增加四个字节。这4个字节可以是什么?它们可以代表符号本身吗?不,因为如果它们是并且我们在 kt 中重命名了一个 sym 值,它会影响 t 在磁盘上的大小,但它不会:

q)update sym:`#.Q.a from `kt where sym=`GOOG
`kt
q)1#t
sym
--------------------------------------------------
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx
q)`:/tmp/t set 1#t
`:/tmp/t
q)hcount `:/tmp/t
34

还是34字节。我认为这 4 个字节是一个索引现在应该很明显了,但是什么的索引呢?它是必须准确称为 sym 的列的索引吗?显然不是,不是。

q)kt:`foo xcol kt
q)t
sym
--------------------------------------------------
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx
AMZN
FB
FB

kt 中不再有名为 sym 的列,但 t 完全没有改变!我们可以更进一步,在 kt 中更改 foo(例如 sym)的类型:

q)update foo:-1 -2 -3.0 from `kt
`kt
q)t
sym
---
-1
-1
-2
-3
-3

它不仅改变了 t,它也改变了它的 meta:

q)meta t
c  | t f  a
---| ------
sym| f kt
q)/  ^------- used to be s

我希望现在很清楚,kdb 存储了引用 table 的键列的 4 字节索引和 table 的名称(但不是键列名称!)。如果引用的 table 丢失,kdb 无法重建原始数据并显示裸索引。如果需要通过网络发送引用 table,则索引将替换为实际值,以便接收方可以看到真实数据。