2

在下表中,当 Dept 字段中的 Data 被编码和存储时,值为 10 的 Dept 如何知道它的 Age 值为 38。

身份证部年龄

1 10 60

2 10 38

3 10 49

对于行存储,我知道我检查 ID 2 并获取整行的数据。

但是,当 ID 2 在列式存储中并且 Dept 信息采用编码形式时,我无法理解如何为 ID 2 检索数据。

你能帮我理解我是否遗漏了一些明显的东西吗?

4

3 回答 3

2

首先,让我们考虑未编码形式的列数据:

ID值为 2 是列中的第二个元素,因此要获取Dept并且Age所有需要做的就是获取它们的第二个元素。

现在以编码(压缩)形式,您可以查看范围内的数据。例如Dept可以编码为 3*10,因此范围 1-3 的值为 10。要检索 中的第二个元素Dept,数据库必须查找包含第二个元素的范围。那将是范围 1-3,其值为 10。

或者以另一种方式看待:为了Dept以顺序方式到达位置 4,系统会看到一组 3 个元素被压缩为 1 个值,因此该组之后的项目(可能是一组新的相同值)将包含第四个元素的值。

为了加快速度,系统当然会保留一个位置索引,以便能够(半)直接跳转到某个范围的值(并且这些范围/组将存储在块中,例如每个 1-8 kB -例如,在B+ 树中,尤其是当需要稍后插入值时)。

另一种可能性是将这些组(范围值及其 rle 前缀)存储在块中,跟踪每个块的第一个和(或唯一)最后一个项目索引,并解压缩包含我们索引值的块寻找。然后计算该解压缩块中项目的偏移量。这将取决于用于在该块中存储数据的压缩类型。


另一方面,在大多数情况下,我们不需要记录中的所有数据,这就是基于列的数据存储如此有趣的原因。

让我们考虑一个有 10 亿条记录的表,每条记录 200 字节(字符串数据等)和一个有 10 GB 可用 RAM 的系统(我的记录数足够大,所以表不适合内存)。所以这是 200 GB 的数据。

现在假设我们想要某个列(一个 4 字节整数列)的总和。要计算基于记录的表的总和,我们必须每 200 字节读取一次值,并且由于数据是从磁盘中读取的 4kB 页面,我们必须读取完整的 200GB。在 100MB/秒的普通磁盘上需要 2000 秒。

如果我们将数据按列分开,即使是未压缩的数据,我们也只需要读取 4GB 的数据(可能已经在内存中)。如果列被压缩,比如 10:1,那将只有 400MB。如果数据是稀疏的(比如很多零或空值),那将更少。此外,要对 100 个相同值的范围求和,只需 100*value 而不是从磁盘读取 100*200 字节,或者如果它们为零,甚至跳过该范围。

还有一个额外的速度增益,因为所有数据(所有值都靠在一起)将从 L1 CPU 缓存中访问,这比访问主内存要快得多。

于 2017-03-02T15:10:11.020 回答
1

这里没有什么可理解的!数据表示与 Vertica 如何将数据写入您的 FS 无关。

编码用于优化数据获取过程。

至于基于行与基于列,ROWKEY(内部数据库)的概念对于两者都是相同的 ROWKEY 由您的数据库引擎维护并且“它以神秘的方式工作”:)

我简称 Encoding 是用于 write & read ,你不会看到编码的二进制代码,你会看到编码数据的表示。

于 2017-03-02T22:47:58.983 回答
0

第一:Vertica 使用许多不同的编码类型。RLE 只是可能的选项之一(适用于低基数、已排序的列)。请记住,某些编码可以减少存储大小(很多)但会增加 CPU 使用率。

第二:如果你想看到“RLE in action”,请查看手册的其他部分,提供清晰简洁的解释(我认为图片有很大帮助)。

第三:在您的示例表中选择正确的编码 - 就存储而言 - 非常容易。例如,如果前两列已排序,我会说第一列的 COMMONDELTA_COMP 和第二列的 RLE。但是 - 一般而言 - 当您有大量数据时,您可能希望使用 Vertica 的数据库设计器来自动选择“正确”的编码......

于 2017-03-02T18:49:06.100 回答