序列化外键表在kdb内部的工作原理

序列化外键表在kdb内部的工作原理,kdb,Kdb,我有一个键控表(引用表),使用外键链接到引用表,并使用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/u

我有一个键控表(引用表),使用外键链接到引用表,并使用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
如果在此之后执行
metat
,则会失败,期望kt作为外键。 如果我按预期打印t,它会在表t的sym列中显示索引值

因此,问题出现了:

  • 由于kdb在磁盘上存储每个表(即c、t、f、a)的元及其相应的值,表t序列化在内部是如何工作的

  • 这些值如何(以二进制格式的哪种形式)存储在文件t中

    -rw-r--r--1 uts员工100 4月13日23:09 t


  • 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
    
    我只在
    t
    中留下了一列-
    sym
    ,因为
    vol
    与问题无关。让我们先在没有任何数据的情况下保存
    t

    现在我们知道,当它为空时,表示
    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将无法重建原始数据并显示裸索引。需要通过导线发送参考表,然后用实际值替换索引,以便接收方可以看到实际数据。

    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
    
    我只在
    t
    中留下了一列-
    sym
    ,因为
    vol
    与问题无关。让我们先在没有任何数据的情况下保存
    t

    现在我们知道,当它为空时,表示
    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将无法重建原始数据并显示裸索引。如果需要通过导线发送参考表,则用实际值替换索引,以便接收方可以看到实际数据