diff --git a/DataIngestion/datamanage.md b/DataIngestion/datamanage.md index 1eef3b8..c0bd4dc 100644 --- a/DataIngestion/datamanage.md +++ b/DataIngestion/datamanage.md @@ -1 +1,2 @@ - \ No newline at end of file + +### 压缩与重新索引 \ No newline at end of file diff --git a/DataIngestion/ingestion.md b/DataIngestion/ingestion.md index e718fe4..fa58cb1 100644 --- a/DataIngestion/ingestion.md +++ b/DataIngestion/ingestion.md @@ -95,14 +95,223 @@ Rollup由 `granularitySpec` 中的 `rollup` 配置项控制。 默认情况下 ``` SELECT SUM("cnt") / COUNT(*) * 1.0 FROM datasource ``` + +在这个查询中,`cnt` 应该引用在摄取时指定的"count"类型Metrics。有关启用汇总时计数工作方式的详细信息,请参阅"架构设计"页上的 [计数接收事件数](../DataIngestion/schemadesign.md#计数接收事件数)。 + +最大化Rollup的提示: +* 一般来说,拥有的维度越少,维度的基数越低,您将获得更好的汇总比率 +* 使用 [Sketches](schemadesign.md#Sketches高基维处理) 避免存储高基数维度,因为会损害汇总比率 +* 在摄入时调整 `queryGranularity`(例如,使用 `PT5M` 而不是 `PT1M` )会增加Druid中两行具有匹配时间戳的可能性,并可以提高汇总率 +* 将相同的数据加载到多个Druid数据源中是有益的。有些用户选择创建禁用汇总(或启用汇总,但汇总比率最小)的"完整"数据源和具有较少维度和较高汇总比率的"缩写"数据源。当查询只涉及"缩写"集里边的维度时,使用该数据源将导致更快的查询时间,这种方案只需稍微增加存储空间即可完成,因为简化的数据源往往要小得多。 +* 如果您使用的 [尽力而为的汇总(best-effort rollup)](#) 摄取配置不能保证[完全汇总(perfect rollup)](#),则可以通过切换到保证的完全汇总选项,或在初始摄取后在[后台重新编制(reindex)](./datamanage.md#压缩与重新索引)数据索引,潜在地提高汇总比率。 + #### 最佳rollup VS 尽可能rollup +一些Druid摄取方法保证了*完美的汇总(perfect rollup)*,这意味着输入数据在摄取时被完美地聚合。另一些则提供了*尽力而为的汇总(best-effort rollup)*,这意味着输入数据可能无法完全聚合,因此可能有多个段保存具有相同时间戳和维度值的行。 + +一般来说,提供*尽力而为的汇总(best-effort rollup)*的摄取方法之所以这样做,是因为它们要么是在没有清洗步骤(这是*完美的汇总(perfect rollup)*所必需的)的情况下并行摄取,要么是因为它们在接收到某个时间段的所有数据(我们称之为*增量发布(incremental publishing)*)之前完成并发布段。在这两种情况下,理论上可以汇总的记录可能会以不同的段结束。所有类型的流接收都在此模式下运行。 + +保证*完美的汇总(perfect rollup)*的摄取方法通过额外的预处理步骤来确定实际数据摄取阶段之前的间隔和分区。此预处理步骤扫描整个输入数据集,这通常会增加摄取所需的时间,但提供完美汇总所需的信息。 + +下表显示了每个方法如何处理汇总: +| **方法** | **如何工作** | +| - | - | +| [本地批](native.md) | 基于配置,`index_parallel` 和 `index` 可以是完美的,也可以是最佳的。 | +| [Hadoop批](hadoopbased.md) | 总是 perfect | +| [Kafka索引服务](kafka.md) | 总是 best-effort | +| [Kinesis索引服务](kinesis.md) | 总是 best-effort | + ### 分区 #### 为什么分区 + +数据源中段的最佳分区和排序会对占用空间和性能产生重大影响 +。 +Druid数据源总是按时间划分为*时间块*,每个时间块包含一个或多个段。此分区适用于所有摄取方法,并基于摄取规范的 `dataSchema` 中的 `segmentGranularity`参数。 + +特定时间块内的段也可以进一步分区,使用的选项根据您选择的摄取类型而不同。一般来说,使用特定维度执行此辅助分区将改善局部性,这意味着具有该维度相同值的行存储在一起,并且可以快速访问。 + +通常,通过将数据分区到一些常用来做过滤操作的维度(如果存在的话)上,可以获得最佳性能和最小的总体占用空间。而且,这种分区通常会改善压缩性能而且还往往会提高查询性能(用户报告存储容量减少了三倍)。 + +> [!WARNING] +> 分区和排序是最好的朋友!如果您确实有一个天然的分区维度,那么您还应该考虑将它放在 `dimensionsSpec` 的 `dimension` 列表中的第一个维度,它告诉Druid按照该列对每个段中的行进行排序。除了单独分区所获得的改进之外,这通常还会进一步改进压缩。 +> 但是,请注意,目前,Druid总是首先按时间戳对一个段内的行进行排序,甚至在 `dimensionsSpec` 中列出的第一个维度之前,这将使得维度排序达不到最大效率。如果需要,可以通过在 `granularitySpec` 中将 `queryGranularity` 设置为等于 `segmentGranularity` 的值来解决此限制,这将把段内的所有时间戳设置为相同的值,并将"真实"时间戳保存为[辅助时间戳](./schemadesign.md#辅助时间戳)。这个限制可能在Druid的未来版本中被移除。 + #### 如何设置分区 +并不是所有的摄入方式都支持显式的分区配置,也不是所有的方法都具有同样的灵活性。在当前的Druid版本中,如果您是通过一个不太灵活的方法(如Kafka)进行初始摄取,那么您可以使用 [重新索引的技术(reindex)](./datamanage.md#压缩与重新索引),在最初摄取数据后对其重新分区。这是一种强大的技术:即使您不断地从流中添加新数据, 也可以使用它来确保任何早于某个阈值的数据都得到最佳分区。 + +下表显示了每个摄取方法如何处理分区: +| **方法** | **如何工作** | +| - | - | +| [本地批](native.md) | 通过 `tuningConfig` 中的 [`partitionsSpec`](./native.md#partitionsSpec) | +| [Hadoop批](hadoopbased.md) | 通过 `tuningConfig` 中的 [`partitionsSpec`](./native.md#partitionsSpec) | +| [Kafka索引服务](kafka.md) | Druid中的分区是由Kafka主题的分区方式决定的。您可以在初次摄入后 [重新索引的技术(reindex)](./datamanage.md#压缩与重新索引)以重新分区 | +| [Kinesis索引服务](kinesis.md) | Druid中的分区是由Kinesis流的分区方式决定的。您可以在初次摄入后 [重新索引的技术(reindex)](./datamanage.md#压缩与重新索引)以重新分区 | + +> [!WARNING] +> +> 注意,当然,划分数据的一种方法是将其加载到分开的数据源中。这是一种完全可行的方法,当数据源的数量不会导致每个数据源的开销过大时,它可以很好地工作。如果使用这种方法,那么可以忽略这一部分,因为这部分描述了如何在单个数据源中设置分区。 +> +> 有关将数据拆分为单独数据源的详细信息以及潜在的操作注意事项,请参阅 [多租户注意事项](../Querying/multitenancy.md)。 + ### 摄入规范 + +无论使用哪一种摄入方式,数据要么是通过一次性[tasks](taskrefer.md)或者通过持续性的"supervisor"(运行并监控一段时间内的一系列任务)来被加载到Druid中。 在任一种情况下,task或者supervisor的定义都在*摄入规范*中定义。 + +摄入规范包括以下三个主要的部分: +* [`dataSchema`](#dataschema), 包含了 [`数据源名称`](#datasource), [`主时间戳列`](#timestampspec), [`维度`](#dimensionspec), [`指标`](#metricsspec) 和 [`转换与过滤`](#transformspec) +* [`ioConfig`](#ioconfig), 该部分告诉Druid如何去连接数据源系统以及如何去解析数据。 更多详细信息,可以看[摄入方法](#摄入方式)的文档。 +* [`tuningConfig`](#tuningconfig), 该部分控制着每一种[摄入方法](#摄入方式)的不同的特定调整参数 + +一个 `index_parallel` 类型任务的示例摄入规范如下: +``` +{ + "type": "index_parallel", + "spec": { + "dataSchema": { + "dataSource": "wikipedia", + "timestampSpec": { + "column": "timestamp", + "format": "auto" + }, + "dimensionsSpec": { + "dimensions": [ + { "type": "string", "page" }, + { "type": "string", "language" }, + { "type": "long", "name": "userId" } + ] + }, + "metricsSpec": [ + { "type": "count", "name": "count" }, + { "type": "doubleSum", "name": "bytes_added_sum", "fieldName": "bytes_added" }, + { "type": "doubleSum", "name": "bytes_deleted_sum", "fieldName": "bytes_deleted" } + ], + "granularitySpec": { + "segmentGranularity": "day", + "queryGranularity": "none", + "intervals": [ + "2013-08-31/2013-09-01" + ] + } + }, + "ioConfig": { + "type": "index_parallel", + "inputSource": { + "type": "local", + "baseDir": "examples/indexing/", + "filter": "wikipedia_data.json" + }, + "inputFormat": { + "type": "json", + "flattenSpec": { + "useFieldDiscovery": true, + "fields": [ + { "type": "path", "name": "userId", "expr": "$.user.id" } + ] + } + } + }, + "tuningConfig": { + "type": "index_parallel" + } + } +} +``` + +该部分中支持的特定选项依赖于选择的[摄入方法](#摄入方式)。 更多的示例,可以参考每一种[摄入方法](#摄入方式)的文档。 + +您还可以不用编写一个摄入规范,可视化的加载数据,该功能位于 [Druid控制台](../Operations/manageui.md) 的 "Load Data" 视图中。 Druid可视化数据加载器目前支持 [Kafka](kafka.md), [Kinesis](kinesis.md) 和 [本地批](native.md) 模式。 + #### `dataSchema` +> [!WARNING] +> +> `dataSchema` 规范在0.17.0版本中做了更改,新的规范支持除*Hadoop摄取方式*外的所有方式。 可以在 [过时的 `dataSchema` 规范]()查看老的规范 + +`dataSchema` 包含了以下部分: +* [`数据源名称`](#datasource), [`主时间戳列`](#timestampspec), [`维度`](#dimensionspec), [`指标`](#metricsspec) 和 [`转换与过滤`](#transformspec) + +一个 `dataSchema` 如下: +``` +"dataSchema": { + "dataSource": "wikipedia", + "timestampSpec": { + "column": "timestamp", + "format": "auto" + }, + "dimensionsSpec": { + "dimensions": [ + { "type": "string", "page" }, + { "type": "string", "language" }, + { "type": "long", "name": "userId" } + ] + }, + "metricsSpec": [ + { "type": "count", "name": "count" }, + { "type": "doubleSum", "name": "bytes_added_sum", "fieldName": "bytes_added" }, + { "type": "doubleSum", "name": "bytes_deleted_sum", "fieldName": "bytes_deleted" } + ], + "granularitySpec": { + "segmentGranularity": "day", + "queryGranularity": "none", + "intervals": [ + "2013-08-31/2013-09-01" + ] + } +} +``` + ##### `dataSource` +`dataSource` 位于 `dataSchema` -> `dataSource` 中,简单的标识了数据将被写入的数据源的名称,示例如下: +``` +"dataSource": "my-first-datasource" +``` ##### `timestampSpec` +`timestampSpec` 位于 `dataSchema` -> `timestampSpec` 中,用来配置 [主时间戳](#timestampspec), 示例如下: +``` +"timestampSpec": { + "column": "timestamp", + "format": "auto" +} +``` +> [!WARNING] +> 概念上,输入数据被读取后,Druid会以一个特定的顺序来对数据应用摄入规范: 首先 `flattenSpec`(如果有),然后 `timestampSpec`, 然后 `transformSpec` ,最后是 `dimensionsSpec` 和 `metricsSpec`。在编写摄入规范时需要牢记这一点 + +`timestampSpec` 可以包含以下的部分: + +
字段 | +描述 | +默认值 | + + +
---|---|---|
column | +要从中读取主时间戳的输入行字段。 不管这个输入字段的名称是什么,主时间戳总是作为一个名为"__time"的列存储在您的Druid数据源中 |
+ timestamp | +
format | +
+ 时间戳格式,可选项有:
+
|
+ auto | +
missingValue | +用于具有空或缺少时间戳列的输入记录的时间戳。应该是ISO8601格式,如"2000-01-01T01:02:03.456" 。由于Druid需要一个主时间戳,因此此设置对于接收根本没有任何时间戳的数据集非常有用。 |
+ none | +