盘区(数据分片)

概述

Kusto 可以支持含有大量记录(行)和大量数据的表。 为了处理此类大型表,每个表的数据被划分为较小的“块”,称为数据分片或盘区(这两个术语是同义词) 。 表的所有盘区的并集保存表的数据。 单个盘区将保持小于单个节点的容量,并且盘区分散在群集的节点上,从而实现横向扩展。

盘区就像一种小型表。 它包含数据和元数据,以及其创建时间和与其数据关联的可选标记等信息。 此外,盘区通常保存能让 Kusto 高效查询数据的信息。 例如盘区中每列数据的索引和编码字典(如果已对列数据进行编码)。 因此,表的数据是表的盘区中所有数据的并集。

盘区是不可变的,并且永远不能修改。 只能查询它、将它重新分配给另一个节点或从表中删除它。 可通过以下方式进行数据修改:创建一个或多个新盘区,并将旧盘区与新盘区进行事务交换。

盘区保存物理上按列排列的记录的集合。 此方法称为分栏式存储。 利用它可以高效地对数据进行编码和压缩,因为同一列中的不同值经常彼此类似。 它还支持更高效地查询大量数据,因为只需加载查询所使用的列。 在内部,盘区内的每个数据列将细分为若干个段,段分为若干个块。 这种分隔对查询而言并不能观察到,这可使 Kusto 优化列压缩和索引编制。

为了保持查询效率,较小的盘区将合并到较大的盘区中。 根据配置的合并策略分片策略,合并作为后台过程自动完成。 合并盘区可减少跟踪大量盘区带来的管理开销。更重要的是,它可使 Kusto 优化其索引并改进压缩。

某个盘区达到特定限制(如大小)后,盘区合并将停止,因为超过特定点后,合并非但不会提高效率,反而会降低效率。

在表上定义数据分区策略时,盘区在创建后将经历另一个后台过程(后期引入)。 此过程重新引入源盘区中的数据,并创建“同类”盘区,其中作为表的“分区键”的列的值全部属于同一分区。 如果策略包括“哈希分区键”,属于同一分区的所有同类盘区将被分配到群集中的同一数据节点。

备注

盘区级别的操作(如合并或更改盘区标记)不会修改现有盘区。 而是基于现有源盘区在这些操作中创建新的盘区。 新的盘区将在单个事务中替换其前身。

常见的盘区生命周期:

  1. 盘区由“引入”操作创建。
  2. 盘区与其他盘区合并。 如果要合并的盘区较小,Kusto 实际上会对其执行引入过程,称为“重新生成”。 在盘区达到一定大小后,只对索引执行合并。 不会修改存储中盘区的数据项目。
  3. 由于保留策略的原因,合并的盘区(该盘区的世系可能追溯到其他合并的盘区)最终会被删除。 删除盘区时,根据时间(旧的盘区 x 小时/天),在计算中使用合并盘区中最新盘区的创建日期。

盘区创建时间

对于每个盘区而言,创建时间是关键信息之一。 此时间用于:

  1. 保留 - 较早创建的盘区将较早被删除。
  2. 缓存 - 最近创建的盘区将保存在热缓存
  3. 采样 - 使用查询操作(例如 take)时,建议使用最近的盘区

事实上,Kusto 会跟踪每个区的两个 datetime 值:MinCreatedOnMaxCreatedOn。 最初,这两个值是相同的。 如果该盘区与其他盘区合并,则新值将与合并盘区的原始最小值和最大值保持一致。

通常,会根据引入盘区中的数据的时间来设置盘区的创建时间。 客户端可以选择覆盖该盘区的创建时间,方法是在 ingestion 属性中提供备用创建时间。 如果出于保留目的,客户端想要重新引入数据并且不希望它看起来像“迟到”的数据,则覆盖很有用。

盘区标记

Kusto 支持将多个可选盘区标记附加到盘区,作为其元数据的一部分。 盘区标记(或只是标记)是与盘区关联的字符串。 可以使用 .show extents 命令查看与某个盘区关联的标记,并使用 extent-tags() 函数查看与某个盘区内的记录相关联的标记。 盘区标记可用于高效地描述盘区内的所有数据所共有的属性。 例如,可以在引入期间添加盘区标记,指示引入数据的源,并在稍后使用该标记。 因为盘区描述数据,因此当两个或多个盘区合并时,它们的相关标记也将合并。 生成的盘区的标记将是这些合并盘区的所有标记的并集。

Kusto 向所有其值具有格式“前缀 后缀” 的盘区标记分配特殊含义,其中“前缀”是以下项之一:

  • drop-by:
  • ingest-by:

'drop-by:' 盘区标记

drop-by: 前缀开头的标记可用于控制要合并的其他盘区。 具有相同的 drop-by: 标记集的盘区可合并在一起,但如果它们具有不同的 drop-by: 标记集,则无法与其他盘区合并。

示例

1. 哪些盘区可合并在一起?

如果:

  • 盘区 1 具有以下标记:drop-by:bluedrop-by:redgreen
  • 盘区 2 具有以下标记:drop-by:redyellow
  • 盘区 3 具有以下标记:purpledrop-by:reddrop-by:blue

那么:

  • 盘区 1 和 2 无法合并,因为它们有不同的 drop-by 标记集。
  • 盘区 2 和 3 无法合并,因为它们有不同的 drop-by 标记集。
  • 盘区 1 和 3 可以合并,因为它们有相同的 drop-by 标记集。

2. 使用 drop-by 标记作为盘区级别操作的一部分

可根据盘区的 drop-by: 标记发出命令来删除盘区。

.ingest ... with @'{"tags":"[\"drop-by:2016-02-17\"]"}'

.drop extents <| .show table MyTable extents where tags has "drop-by:2016-02-17" 

警告

  • 不要滥用 drop-by 标记。 以上述方式删除数据仅适用于很少发生的事件。
    • 它不应该用于替换记录级数据,并且要求以这种方式标记的数据很庞大。
    • 如果尝试为每个记录、少量记录或文件提供唯一标记,可能会对性能产生严重影响。
  • 如果引入数据后,在一段时间内不需要 drop-by 标记,建议删除标记

'ingest-by:' 盘区标记

ingest-by: 前缀开头的标记可用于确保数据仅引入一次。 如果已存在具有此特定 ingest-by: 标记的盘区,则可以发出 ingestIfNotExists 属性命令阻止数据引入。 tagsingestIfNotExists 的值都是字符串数组,序列化为 JSON。

以下示例仅引入数据一次。 第二个和第三个命令不执行任何操作:

.ingest ... with (tags = '["ingest-by:2016-02-17"]')

.ingest ... with (ingestIfNotExists = '["2016-02-17"]')

.ingest ... with (ingestIfNotExists = '["2016-02-17"]', tags = '["ingest-by:2016-02-17"]')

备注

通常,引入命令可能同时包含 ingest-by: 标记和 ingestIfNotExists 属性,并设置为相同的值,如上述第三个命令中所示。

警告

  • 不建议过度使用 ingest-by 标记。
  • 如果已知馈送 Kusto 的管道有数据重复,我们建议在将数据引入 Kusto 之前,尽可能解决这些重复项。
  • 尝试为每个引入调用设置唯一的 ingest-by 标记可能会对性能产生严重影响。
  • 如果在数据引入后的某个时间段内不需要此类标记,则建议删除区标记