tl;dr 外键存储为一个由引用表的键列的 4 字节索引加上外键引用的表的名称组成的向量。
据我所知,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
我只留下了一列 - sym - 在 t 中,因为 vol 与问题无关。让我们先保存t 没有任何数据:
q)`:/tmp/t set 0#t
`:/tmp/t
q)hcount `:/tmp/t
30
现在我们知道,当 t 为空时,它需要 30 个字节来表示。让我们看看当我们开始向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:`$50#.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,它也改变了它的元:
q)meta t
c | t f a
---| ------
sym| f kt
q)/ ^------- used to be s
我希望现在很清楚 kdb 存储了引用表的键列的 4 字节索引和表的名称(但不是键列名称!)。如果缺少引用的表,kdb 将无法重建原始数据并显示裸索引。它需要通过网络发送参考表,然后将索引替换为实际值,以便接收方可以看到真实数据。