【问题标题】:How serializing foreign keyed table works internally in kdb序列化外键表如何在 kdb 内部工作
【发布时间】:2020-04-13 17:47:04
【问题描述】:

我有一个使用外键链接到引用表的键控表(引用表),我使用 set 运算符对两个表进行序列化。

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

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

q)delete kt,t from `.

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

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

如果我在此之后执行meta t,它将失败,期望 kt 作为外键。 如果我打印 t,它会按预期显示表 t 的 sym 列中的索引值。

那么问题来了——

  1. 由于 kdb 将每个表的元数据(即 c、t、f、a)及其对应值存储在磁盘上,表 t 序列化在内部如何工作?

  2. 这些值是如何存储在文件 t 中的。

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

【问题讨论】:

    标签: kdb


    【解决方案1】:

    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 将无法重建原始数据并显示裸索引。它需要通过网络发送参考表,然后将索引替换为实际值,以便接收方可以看到真实数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-06
      • 1970-01-01
      • 2021-12-06
      • 1970-01-01
      • 1970-01-01
      • 2019-06-17
      • 1970-01-01
      相关资源
      最近更新 更多