序列化外键 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 列中显示索引值
那么,问题来了——
由于kdb在磁盘上存储了每个table(即c,t,f,a)的meta及其对应的值,那么tablet序列化在内部是如何工作的?
这些值如何(以二进制格式以何种形式)存储在文件 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,则索引将替换为实际值,以便接收方可以看到真实数据。
我有一个使用外键链接到引用 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.
那么,问题来了——
由于kdb在磁盘上存储了每个table(即c,t,f,a)的meta及其对应的值,那么tablet序列化在内部是如何工作的?
这些值如何(以二进制格式以何种形式)存储在文件 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,则索引将替换为实际值,以便接收方可以看到真实数据。