

要获得与亚马逊 Timestream 类似的功能 LiveAnalytics，可以考虑适用于 InfluxDB 的亚马逊 Timestream。适用于 InfluxDB 的 Amazon Timestream 提供简化的数据摄取和个位数毫秒级的查询响应时间，以实现实时分析。点击[此处](https://docs.aws.amazon.com//timestream/latest/developerguide/timestream-for-influxdb.html)了解更多信息。

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 数据建模
<a name="data-modeling"></a>

Amazon Timestream for 旨在收集、存储和分析来自应用程序和设备的时间序列数据，这些数据会发出一系列带有时间戳的数据。 LiveAnalytics 为了获得最佳性能，发送到 Timestream 的数据 LiveAnalytics 必须具有时间特征，并且时间必须是数据的典型组成部分。

Timestream for 允许您 LiveAnalytics 灵活地以不同的方式对数据进行建模，以满足您的应用程序需求。本节将介绍其中几种模式，并为您提供优化成本和性能的指南。熟悉维度和度量等关键 [概念 Amazon Timestream LiveAnalytics](concepts.md)。在本节中，您将了解以下内容，决定是创建单个表还是多个表以存储数据：
+ 哪些数据放入同一个表中，而哪些数据需拆分到多个表和数据库中。
+ 如何在 LiveAnalytics 多测量记录的 Timestream 与单测量记录之间进行选择，以及使用多测量记录进行建模的好处，尤其是在您的应用程序同时跟踪多个测量值时。
+ 哪些属性应作为维度建模，哪些应作为度量建模。
+ 如何有效使用度量名称属性以优化查询延迟。

**Topics**
+ [单表与多表](#data-modeling-singleVmultitable)
+ [多度量记录与单度量记录](#data-modeling-multiVsinglerecords)
+ [维度和度量](#data-modeling-dimensionsmeasures)
+ [将度量名称与多度量记录结合使用](#data-modeling-measurenamemulti)
+ [对多度量记录进行分区的建议](#data-modeling-multi-measure-partitioning)

## 单表与多表
<a name="data-modeling-singleVmultitable"></a>

在应用程序中对数据进行建模时，另一重要方面是如何将数据建模为表和数据库。Timestream 中的数据库和表 LiveAnalytics 是用于访问控制的抽象，用于指定 KMS 密钥、保留期等。Timestream 用于 LiveAnalytics自动对您的数据进行分区，旨在扩展资源以匹配应用程序的摄取、存储、查询负载和要求。

Timestream 中的表 LiveAnalytics 可以扩展到存储的 PB 级数据和每秒写入数十千兆字节的数据量。查询每小时可处理数百 TB 数据。Timestream 中的查询 LiveAnalytics 可以跨越多个表和数据库，提供联接和并集，让您可以无缝访问多个表和数据库中的数据。因此，在决定如何在 Timestream 中组织数据时，数据规模或请求量通常不是主要考虑的问题。 LiveAnalytics在决定将哪些数据放入相同的表中，还是分散在不同表或不同数据库的表中时，需要考虑以下重要事项。
+ 按表的粒度支持数据留存策略（内存存储保留、磁性存储保留等）。因此，需要不同保留策略的数据应放入不同的表中。
+ AWS KMS 用于加密数据的密钥是在数据库级别配置的。因此，不同的加密密钥要求意味着数据需放入不同的数据库中。
+ Timestream for LiveAnalytics 支持在表和数据库的粒度上进行基于资源的访问控制。在决定将哪些数据写入相同的表，哪些数据写入不同的表时，请考虑访问控制要求。
+ 在决定将哪些数据存储于哪个表中时，需注意维度数量、度量名称和多度量属性名称的[限制](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html)。
+ 在决定如何组织数据时，请考虑查询工作负载和访问模式，因为查询延迟和写入查询的难易程度将取决于这些因素。
  + 如果将经常查询的数据存储在相同的表中，这通常会简化写入查询的方式，从而避免写入联接、并集或通用表表达式。这通常还可以降低查询延迟。您可以使用维度和度量名称上的谓词，以筛选与查询相关的数据。

    例如，假设存储来自六大洲设备的数据。如果查询经常跨洲访问数据以获取全球汇总视图，那么将来自这些洲的数据存储在相同的表中将使查询更易于写入。另一方面，如果将数据存储在不同的表上，仍可在同一查询中合并数据，但需要写入查询以跨表合并数据。
  + Timestream for 对您的数据 LiveAnalytics 使用自适应分区和索引，因此仅对与您的查询相关的数据向查询收费。例如，如果您有一个表用于存储来自六大洲百万台设备的数据，如果查询中包含形式为 `WHERE device_id = 'abcdef'` 或 `WHERE continent = 'North America'` 的谓词，则仅对设备或所在洲的数据进行查询而计费。
  + 只要有可能，如果您使用度量名称将同一表中不同时发出或不经常查询的数据分开，那么使用诸如`WHERE measure_name = 'cpu'`查询之类的谓词，不仅可以获得计量优势，Timestream for LiveAnalytics 还可以有效地消除查询谓词中没有使用度量名称的分区。这使您能够将具有不同度量名称的相关数据存储在相同的表中，而不会影响查询延迟或成本，同时可避免将数据分散到多个表中。度量名称本质上用于对数据进行分区，并修剪与查询无关的分区。

## 多度量记录与单度量记录
<a name="data-modeling-multiVsinglerecords"></a>

Timestream for LiveAnalytics 允许您写入每条记录有多个度量（多度量）或每条记录单个度量（单度量）的数据。

**多度量记录**

在许多使用案例中，您正在跟踪的设备或应用程序可能在同一时间戳发出多个指标或事件。在这种情况下，可将同一时间戳输出的所有指标存储在同一多度量记录中。也就是说，存储在同一多度量记录中的所有度量，在数据的同一行中显示为不同的列。

例如，假设应用程序正从同时测量的设备输出 cpu、内存和 disk\$1iops 等指标。以下是此类表的示例，其中同时输出的多个指标存储在同一行中。您会发现两个主机每秒输出一次指标。


| 主机名 | measure\$1name | 时间 | cpu | 内存 | disk\$1iops | 
| --- | --- | --- | --- | --- | --- | 
| host-24Gju | metrics | 2021-12-01 19:00:00 | 35 | 54.9 | 38.2 | 
| host-24Gju | metrics | 2021-12-01 19:00:01 | 36 | 58 | 39 | 
| host-28Gju | metrics | 2021-12-01 19:00:00 | 15 | 55 | 92 | 
| host-28Gju | metrics | 2021-12-01 19:00:01 | 16 | 50 | 40 | 

**单度量记录**

当您的设备在不同的时间段发出不同的指标，或者您使用在不同时间段（例如，当设备发生变化时）发出的 metrics/events 自定义处理逻辑时，单一测量记录是合适的 reading/state 。由于每个度量都有唯一的时间戳，因此可以将这些度量存储在 Timestream 中各自的记录中。 LiveAnalytics例如，以 IoT 传感器为例，其可跟踪土壤温度和湿度，仅在检测到与之前报告条目存在变化时才会输出记录。以下示例展示使用单度量记录输出此类数据的具体情况。


| device\$1id | measure\$1name | 时间 | measure\$1value::double | measure\$1value::bigint | 
| --- | --- | --- | --- | --- | 
| sensor-sea478 | temperature |  2021-12-01 19:22:32 | 35 | NULL | 
| sensor-sea478 | temperature |  2021-12-01 18:07:51 | 36 | NULL | 
| sensor-sea478 | 湿度 |  2021-12-01 19:05:30 | NULL | 21 | 
| sensor-sea478 | 湿度 |  2021-12-01 19:00:01 | NULL | 23 | 

**比较单度量记录和多度量记录**

Timestream for 允许您 LiveAnalytics 灵活地根据应用程序的要求和特征将数据建模为单度或多度量记录。如果应用程序需要，单个表可同时存储单度量记录和多度量记录。通常，当您的应用程序同时发射多个 measures/events 数据时，通常建议将数据建模为多度量记录，以实现高性能的数据访问和具有成本效益的数据存储。

例如，如果您考虑[DevOps 使用一个跟踪来自数十万台服务器的指标和事件的用例](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/tools/python/perf-scale-workload)，则每台服务器会定期发出 20 个指标和 5 个事件，其中事件和指标会同时即时发出。可以使用单度量记录或多度量记录对该数据进行建模（有关生成的架构，请参阅[开源数据生成器](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/tools/python/perf-scale-workload)）。对于此使用案例，使用多度量记录与单度量记录对数据进行建模的结果如下：
+ *摄取计量*：多度量记录使写入的摄取字节数*减少约 40％*。
+ *摄取批处理*：多度量记录会导致发送的数据批量更大，这意味着客户端需要更少的线程和更少的 CPU 以处理摄取。
+ *存储计量*：多度量记录可将存储空间*减少约 8 倍*，从而显著节省内存存储和磁性存储的存储空间。
+ *查询延迟*：与单度量记录相比，多度量记录可降低大多数查询类型的查询延迟。
+ *查询计量字节*：对于扫描小于 10MB 数据的查询，单度量记录和多度量记录具有可比性。对于访问单个度量且扫描数据量大于 10MB 的查询，单度量记录通常会导致计量的字节数较低。对于涉及三个或更多度量的查询，多度量记录会导致计量的字节数降低。
+ *轻松表达多度量查询*：当查询涉及多个度量时，使用多度量记录对数据进行建模可使查询更易写入且更紧凑。

上述因素将因跟踪的指标数量、数据维度数量等而有所不同。虽然上述示例为单一情况提供具体数据，但在众多应用场景和使用案例中，我们发现当应用程序在同一时刻输出多个度量时，以多度量记录的形式存储数据更为高效。此外，多度量记录为您提供了数据类型的灵活性，并将多个其他值存储为上下文（例如，存储请求 IDs和其他时间戳，稍后将讨论）。

请注意，多度量记录也可对稀疏度量进行建模，例如上述的单度量记录示例：可以使用 `measure_name` 存储度量的名称，也可以使用通用的多度量属性名称，例如使用 `value_double` 存储 `DOUBLE` 度量、使用 `value_bigint` 存储 `BIGINT` 度量、使用 `value_timestamp` 存储其他 `TIMESTAMP` 值等。

## 维度和度量
<a name="data-modeling-dimensionsmeasures"></a>

Timestream 中的表 LiveAnalytics 允许您存储*维度*（标识要存储的 device/data 属性）和度*量*（ metrics/values 您正在跟踪的维度）；有关更多详细信息，[概念 Amazon Timestream LiveAnalytics](concepts.md)请参阅。当您在Timestream上为应用程序建模时 LiveAnalytics，如何将数据映射到维度和度量会影响您的摄取和查询延迟。以下是有关如何将数据建模为维度和度量的指南，可应用于您的使用案例。

**选择维度**

用于标识发送时间序列数据源的数据，天然适合用作维度，即不会随时间推移而变化的属性。例如，如果您的服务器输出指标，则用于标识服务器的属性（例如主机名、区域、机架和可用区）可作为维度候选项。同样，对于具有多个报告时间序列数据的传感器的 IoT 设备，设备 ID 和传感器 ID 等属性可作为维度的候选项。

如果以多度量记录形式写入数据，当对该表执行 `DESCRIBE` 或运行 `SELECT` 语句时，维度和多度量属性将以列的形式呈现于表中。因此，在写入查询时，可在同一查询中自由使用维度和度量。然而，在构建写入记录以摄取数据时，选择哪些属性作为维度属性，哪些属性作为度量值属性时，请注意以下事项：
+ 维度名称、维度值、度量名称和时间戳可唯一标识时间序列数据。Timestream for LiveAnalytics 使用此唯一标识符自动消除重复数据。也就是说，如果 Timestream LiveAnalytics 接收的两个数据点具有相同的维度名称、维度值、度量名称和时间戳值，并且这些值具有相同的版本号，则用于重复数据消除的 Timestream。 LiveAnalytics如果新的写入请求的版本低于 Timestream 中已有的数据 LiveAnalytics，则写入请求将被拒绝。如果新写入请求具有更高的版本，则新值会覆盖旧值。因此，如何选择维度值将影响此重复数据删除行为。
+ 无法更新维度名称和维度值，但可更新度量值。因此，最好将任何可能需要更新的数据建模为度量值。例如，如果工厂车间里有台颜色可变的机器，可将颜色建模为度量值，除非还需要将颜色用作去重所需的标识属性。也就是说，度量值可用于存储仅会随时间推移而缓慢变化的属性。

请注意，Timestream 中的表 LiveAnalytics 不会限制维度名称和值的唯一组合的数量。例如，可将数十亿个这样的唯一值组合存储在表中。然而，正如以下示例所示，谨慎选择维度和度量可以显著优化请求延迟，尤其对于查询而言。

**尺寸 IDs 独特**

如果应用场景要求提供存储每个数据点的唯一标识符（例如，请求 ID、交易 ID 或关联 ID），则将 ID 属性建模为度量值将显著降低查询延迟。使用多度量记录对数据进行建模时，ID 会出现在与其他维度和时间序列数据相同的行中，因此查询可以继续有效地使用这些数据。例如，考虑到服务器发出的每个数据点都具有唯一的请求 ID 属性的[DevOps 用例](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/tools/python/perf-scale-workload)，与将唯一的请求 ID 建模为维度相比，将请求 ID 建模为度量值可以将不同查询类型的查询延迟降低多达 4 倍。

对于并非每个数据点都完全唯一但具有数十万或数百万个唯一值的属性，可使用类似的类比。可将这些属性建模为维度值或度量值。如前所述，如果需在写入路径中对这些值进行去重处理，或在查询中频繁将其用作谓词（例如，在 `WHERE` 子句中对 `device_id = 'abcde'` 等属性的值设置等值谓词，其中应用程序需要追踪数百万台设备），则应将其建模为维度。

**数据类型丰富，具备多度量记录**

多度量记录提供灵活选项，以对数据进行有效建模。存储在多度量记录中的数据在表中以列的形式呈现，类似于维度，因此查询维度和度量值同样便捷。上述讨论过的示例中已出现其中一些模式。以下是其他模式，可有效使用多度量记录以满足应用程序的使用案例需求。

多度量记录支持以下数据类型的属性：`DOUBLE`、`BIGINT`、`VARCHAR`、`BOOLEAN` 和 `TIMESTAMP`。因此，多度量记录自然适合不同类型的属性：
+ *位置信息*：例如，如果需要跟踪某个位置（以纬度和经度表示），与将其存储为 `VARCHAR` 维度相比，将其建模为多度量属性可降低查询延迟，尤其是当经纬度存在谓词时。
+ *记录中的多个时间戳*：如果应用场景要求跟踪时间序列记录的多个时间戳，可将其建模为多度量记录中的其他属性。此模式可用于存储带有未来时间戳或过去时间戳的数据。请注意，每条记录仍将使用时间列中的时间戳，以便对记录进行分区、索引和唯一标识。

特别是，如果查询中包含带谓词的数值数据或时间戳，将这些属性建模为多度量属性而非维度将降低查询延迟。这是因为当使用多度量记录支持的丰富数据类型对此类数据进行建模时，如果将此类数据建模为维度，可以直接使用原生数据类型表示谓词，无需将值从 `VARCHAR` 转换为其他数据类型。

## 将度量名称与多度量记录结合使用
<a name="data-modeling-measurenamemulti"></a>

Timestream 中的表 LiveAnalytics 支持名为*度量名称*的特殊属性（或列）。您可以为写入 Timestream 的每条记录为此 LiveAnalytics属性指定一个值。对于单度量记录，自然应使用指标的名称（例如，使用 CPU 或内存表示服务器指标，或使用温度或压力表示传感器指标）。当使用多度量记录时，会对多度量记录中的属性进行命名，这些名称将成为表中的列名。因此，CPU、内存、温度和压力均可成为多度量属性名称。自然而然的问题是：如何有效使用度量名称。

Timestream for LiveAnalytics 使用度量名称属性中的值对数据进行分区和索引。因此，如果表有多个不同的度量名称，并且查询使用这些值作为查询谓词，则 Timestream for LiveAnalytics 可以使用其自定义分区和索引来删除与查询无关的数据。例如，如果您的表具有`cpu`和`memory`度量名称，并且您的查询具有谓词`WHERE measure_name = 'cpu'`，则 Timestream for LiveAnalytics 可以有效地修剪与查询无关的度量名称的数据，例如本示例中具有度量名称内存的行。即使在多度量记录中使用度量名称，此修剪操作仍适用。可有效使用度量名称属性作为表的分区属性。度量名称以及维度名称和值以及时间用于对 LiveAnalytics 表的 Timestream 中的数据进行分区。请注意 LiveAnalytics 表的 Timestream 中允许的唯一度量名称数量的[限制](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html)。另请注意，度量名称也会与度量值数据类型相关联。例如，单个度量名称仅可与一种类型的度量值相关联。该类型可以是 `DOUBLE`、`BIGINT`、`BOOLEAN`、`VARCHAR` 或 `MULTI` 其中之一。使用度量名称存储的多度量记录，其数据类型为 `MULTI`。由于单个多度量记录可以存储多个不同数据类型（`DOUBLE`、`BIGINT`、`VARCHAR`、`BOOLEAN` 和 `TIMESTAMP`）的指标，因此可在多度量记录中关联不同类型的数据。

以下各节将通过若干不同示例说明如何有效利用度量名称属性，将同一表中的不同类型数据进行分组。

**IoT 传感器报告质量和价值**

假设有一个应用程序，用于监控来自 IoT 传感器的数据。每个传感器跟踪不同的度量值，例如温度和压力。除实际值以外，传感器还报告测量值的质量，该指标反映读数的准确性，并标注测量值单位。由于质量、单位和值会同时输出，因此可将其建模为多度量记录，如以下示例数据所示，其中 `device_id` 为维度，`quality`、`value` 和 `unit` 为多度量属性：


| device\$1id | measure\$1name | 时间 | 质量 | 值 | 单位 | 
| --- | --- | --- | --- | --- | --- | 
| sensor-sea478 | temperature | 2021-12-01 19:22:32 | 92 | 35 | c | 
| sensor-sea478 | temperature | 2021-12-01 18:07:51 | 93 | 34 | c | 
| sensor-sea478 | pressure | 2021-12-01 19:05:30 | 98 | 31 | psi | 
| sensor-sea478 | pressure | 2021-12-01 19:00:01 | 24 | 132 | psi | 

此方法使您能够利用多度量记录的优势，同时结合度量名称的值对数据进行分区和修剪。如果查询引用单个度量（例如温度），则可在查询中包含 `measure_name` 谓词。以下是此类查询的示例，该查询还会投影质量高于 90 的测量值单位。

```
SELECT device_id, time, value AS temperature, unit
FROM db.table
WHERE time > ago(1h)
    AND measure_name = 'temperature'
    AND quality > 90
```

在查询上使用`measure_name`谓词可以让 Timestream 有效地修剪与查询无关的分区和数据，从而缩短查询延迟。 LiveAnalytics 

如果所有指标都在相同的时间戳输出，且/或在同一查询中同时查询多个指标，则所有指标也可以存储在同一多度量记录中。例如，您可以使用 temperature\$1quality、temperature\$1value、temperature\$1unit、pressure\$1quality、pressure\$1value 和 pressure\$1unit 等属性构造多度量记录。就决定如何对数据进行建模，先前讨论的关于使用单度量记录与多度量记录对数据进行建模的诸多要点同样适用。根据查询访问模式以及数据生成方式，选择能够优化成本、数据摄取和查询延迟以及便于写入查询的模型。

**同一个表中不同类型的指标**

另一个可将多度量记录与度量名称值结合使用的使用案例，是对来自同一设备但独立输出的不同类型数据进行建模。考虑一下 DevOps 监控用例，其中服务器发出两种类型的数据：定期发出的指标和不规则的事件。这种方法的一个例子是[数据生成器对 DevOps 用例进行建模中讨论的](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/tools/python/perf-scale-workload)架构。在此情况下，您可以使用不同的度量名称，将同一服务器输出的不同类型数据存储在同一个表中。例如，所有同时输出的指标都使用度量名称指标进行存储。所有在与指标不同时间点输出的事件都使用度量名称事件进行存储。表的度量架构（例如，`SHOW MEASURES` 查询的输出）为：


| measure\$1name | data\$1type | Dimensions | 
| --- | --- | --- | 
| events | multi | [\$1"data\$1type":"varchar","dimension\$1name":"availability\$1zone"\$1,\$1"data\$1type":"varchar","dimension\$1name":"microservice\$1name"\$1,\$1"data\$1type":"varchar","dimension\$1name":"instance\$1name"\$1,\$1"data\$1type":"varchar","dimension\$1name":"process\$1name"\$1,\$1"data\$1type":"varchar","dimension\$1name":"jdk\$1version"\$1,\$1"data\$1type":"varchar","dimension\$1name":"cell"\$1,\$1"data\$1type":"varchar","dimension\$1name":"region"\$1,\$1"data\$1type":"varchar","dimension\$1name":"silo"\$1] | 
| metrics | multi | [\$1"data\$1type":"varchar","dimension\$1name":"availability\$1zone"\$1,\$1"data\$1type":"varchar","dimension\$1name":"microservice\$1name"\$1,\$1"data\$1type":"varchar","dimension\$1name":"instance\$1name"\$1,\$1"data\$1type":"varchar","dimension\$1name":"os\$1version"\$1,\$1"data\$1type":"varchar","dimension\$1name":"cell"\$1,\$1"data\$1type":"varchar","dimension\$1name":"region"\$1,\$1"data\$1type":"varchar","dimension\$1name":"silo"\$1,\$1"data\$1type":"varchar","dimension\$1name":"instance\$1type"\$1] | 

在此情况下，您可以发现事件和指标也有不同的维度集，其中事件具有维度 `jdk_version` 和 `process_name`，而指标具有维度 `instance_type` 和 `os_version`。

使用不同的度量名称，可让您写入带有谓词（例如 `WHERE measure_name = 'metrics'`）的查询，以便仅获取指标。此外，将同一实例输出的所有数据存储在同一个表中，意味着您可以写入带有 `instance_name` 谓词的更简单查询语句，以获取该实例的所有数据。例如，形式为 `WHERE instance_name = 'instance-1234'` 且不带 `measure_name` 谓词的谓词将返回特定服务器实例的所有数据。

## 对多度量记录进行分区的建议
<a name="data-modeling-multi-measure-partitioning"></a>

**重要**  
**此部分已弃用！**  
这些建议已经过时。现在，使用[客户定义的分区键](customer-defined-partition-keys.md)可以更有效地控制分区。

我们注意到，在时间序列生态系统中，越来越多的工作负载需要同时满足两大需求：既要处理海量数据的采集与存储，又要在通过高基数维度值集访问数据时实现低延迟的查询响应。

由于这些特性，本节中的建议尤其适用于具有以下特征的客户工作负载：
+ 已采用或计划采用多度量记录。
+ 预计将有大量数据进入系统，且会长期存储其中。
+ 客户工作负载的主要访问（查询）模式要求低延迟响应时间。
+ 请注意，最重要的查询模式都涉及谓词中某种形式的筛选条件。此筛选条件基于高基数维度构建。例如，考虑按照、、serverID UserId DeviceId、主机名等进行的事件或聚合。

在这些情况下，所有多度量值的单一名称并无助益，因为我们的引擎使用多度量名称对数据进行分区，而使用单个值会限制您获得的分区优势。这些记录的分区主要基于两大维度。假设时间在 x 轴上，维度名称的哈希值和 `measure_name` 在 y 轴上。在这些情况下，`measure_name` 的作用近似于分区键。

我们的建议如下：
+ 针对类似前述的使用案例，对数据进行建模时，请使用 `measure_name`，这是主查询访问模式的直接衍生。例如：
  + 使用案例需要从最终用户的角度跟踪应用程序性能和 QoE。这也可能是跟踪单个服务器或 IoT 设备的测量值。
  + 如果要查询和筛选依 UserId据，则需要在摄取时找到与之关联`measure_name`的最佳方式。 UserId
  + 由于多度量表仅能容纳 8192 个不同的度量名称，因此无论采用何种公式，生成的不同值数量都不应超过 8192 个。
+ 对于字符串值，我们成功应用的一种方法是对其进行哈希算法处理。然后使用哈希结果的绝对值与 8192 进行取模运算。

  ```
  measure_name = getMeasureName(UserId)
  int getMeasureName(value) {
      hash_value =  abs(hash(value))
      return hash_value % 8192
  }
  ```
+ 我们还添加了 `abs()`，以删除符号，从而消除值介于 -8192 到 8192 之间的可能性。这应在取模运算之前执行。
+ 采用此方法后，您的查询运行时间将仅需未分区数据模型运行所需时间的一小部分。
+ 查询数据时，请确保在谓词中包含筛选条件，该条件使用 `measure_name` 的新派生值。例如：
  + 

    ```
    SELECT * FROM your_database.your_table 
    WHERE host_name = 'Host-1235' time BETWEEN '2022-09-01' 
        AND '2022-09-18' 
        AND measure_name = (SELECT cast(abs(from_big_endian_64(xxhash64(CAST('HOST-1235' AS varbinary))))%8192 AS varchar))
    ```
  + 这将大幅减少扫描的分区总数，从而确保数据可随时间推移加快转化为查询。

请记住，如果您想从此分区架构中获得好处，则需要在客户端计算哈希值，然后将其 LiveAnalytics 作为静态值传递给 Timestream，以供查询引擎使用。上述示例提供一种验证引擎是否可在需要时解析所生成哈希值的方法。


| 时间 | host\$1name | 地点 | server\$1type | cpu\$1usage | available\$1memory | cpu\$1temp | 
| --- | --- | --- | --- | --- | --- | --- | 
|  2022-09-07 21:48:44 .000000000  |  host-1235  |  us-east1  |  5.8xl  |  55  |  16.2  |  78  | 
|  R2022-09-07 21:48:44 .000000000  |  host-3587  |  us-west1  |  5.8xl  |  62  |  18.1  |  81  | 
|  2022-09-07 21:48:45.000000000  |  host-258743  |  eu-central  |  5.8xl  |  88  |  9.4  |  91  | 
|  2022-09-07 21:48:45 .000000000  |  host-35654  |  us-east2  |  5.8xl  |  29  |  24  |  54  | 
|  R2022-09-07 21:48:45 .000000000  |  host-254  |  us-west1  |  5.8xl  |  44  |  32  |  48  | 

根据我们的建议生成关联的 `measure_name` 时，有两种路径可选，具体取决于您的摄取模式。

1. *对于历史数据的批量摄取*：如果您要使用自己的代码进行批处理，可将转换添加至写入代码中。

   基于前面的示例进行构建。

   ```
           List<String> hosts = new ArrayList<>();
   
           hosts.add("host-1235");
           hosts.add("host-3587");
           hosts.add("host-258743");
           hosts.add("host-35654");
           hosts.add("host-254");
   
           for (String h: hosts){
               ByteBuffer buf2 = ByteBuffer.wrap(h.getBytes());
               partition = abs(hasher.hash(buf2, 0L)) % 8192;
               System.out.println(h + " - " + partition);
   
           }
   ```

   Output

   ```
   host-1235 - 6445
   host-3587 - 6399
   host-258743 - 640
   host-35654 - 2093
   host-254 - 7051
   ```

   生成的数据集    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/timestream/latest/developerguide/data-modeling.html)

1. *对于实时摄取*：您需要在数据传入时实时生成 `measure_name`。

在这两种情况下，我们建议您在两端（摄取和查询）测试哈希生成算法，以确保获得相同结果。

以下是一些基于 `host_name` 生成哈希值的代码示例。

**Example Python**  

```
>>> import xxhash
>>> from bitstring import BitArray
>>> b=xxhash.xxh64('HOST-ID-1235').digest()
>>> BitArray(b).int % 8192
### 3195
```

**Example Go**  

```
package main

import (
    "bytes"
    "fmt"
    "github.com/cespare/xxhash"
)

func main() {
    buf := bytes.NewBufferString("HOST-ID-1235")
    x := xxhash.New()
    x.Write(buf.Bytes())
    // convert unsigned integer to signed integer before taking mod
    fmt.Printf("%f\n", abs(int64(x.Sum64())) % 8192)
}

func abs(x int64) int64 {
    if (x < 0) {
        return -x
    }
    return x
}
```

**Example Java**  

```
import java.nio.ByteBuffer;

import net.jpountz.xxhash.XXHash64;

public class test {
    public static void main(String[] args) {
        XXHash64 hasher = net.jpountz.xxhash.XXHashFactory.fastestInstance().hash64();

        String host = "HOST-ID-1235";
        ByteBuffer buf = ByteBuffer.wrap(host.getBytes());

        Long result = Math.abs(hasher.hash(buf, 0L));
        Long partition = result % 8192;

        System.out.println(result);
        System.out.println(partition);
    }
}
```

**Example Maven 中的依赖项**  

```
        <dependency>
            <groupId>net.jpountz.lz4</groupId>
            <artifactId>lz4</artifactId>
            <version>1.3.0</version>
        </dependency>
```