因为查找数据可能需要很长时间,特别是如果您的超表中有大量数据,所以您可以使用索引来加速从非压缩块(它们使用自己的列式索引)读取操作。

您可以在列的任意组合上创建索引。要将索引定义为 UNIQUEPRIMARY KEY 索引,它必须包含分区列(这通常是时间列)。

您选择在其上创建索引的列取决于您存储的数据类型。当您创建超表时,将 time 列的数据类型设置为 timestamptz 而不是 timestamp。有关更多信息,请参阅 PostgreSQL 时间戳

注意

虽然可以添加不包含 time 列的索引,但这样做会导致非常慢的摄取速度。对于时序数据,在时间列上建立索引允许每个块创建一个索引。

考虑一个简单的示例,其中收集了来自两个位置(名为 officegarage)的温度

(location, time DESC) 上的索引像这样组织

garage-0940
garage-0930
garage-0920
garage-0910
office-0930
office-0920
office-0910

(time DESC, location) 上的索引像这样组织

0940-garage
0930-garage
0930-office
0920-garage
0920-office
0910-garage
0910-office

关于索引的一个好的经验法则是分层考虑。首先选择您通常想要在其上运行等式运算符的列,例如 location = garage。然后完成选择您想要在其上使用范围运算符的列,例如 time > 0930

作为一个更复杂的示例,假设您有许多设备在跟踪 1,000 家不同的零售店。每家店有 100 台设备,以及 5 种不同类型的设备。所有这些设备都将指标报告为 float 值,您决定将所有指标存储在同一个表中,如下所示

CREATE TABLE devices (
time timestamptz,
device_id int,
device_type int,
store_id int,
value float
);

当您创建此表时,会自动在时间列上生成索引,从而更快地根据时间查询您的数据。

如果您想在时间以外的其他内容上查询数据,您可以创建不同的索引。例如,您可能只想查询过去一个月内给定 device_id 的数据。或者您可以查询过去三个月内单个 store_id 的所有数据。

您希望保留时间索引,以便可以快速过滤给定时间范围,并在 device_idstore_id 上添加另一个索引。这将创建一个复合索引。(store_id, device_id, time) 上的复合索引首先按 store_id 排序。每个唯一的 store_id,然后将按 device_id 顺序排序。并且每个具有相同 store_iddevice_id 的条目然后按 time 排序。要创建此索引,请使用此命令

CREATE INDEX ON devices (store_id, device_id, time DESC);

当您的超表上具有此复合索引时,您可以运行各种不同的查询。以下是一些示例

SELECT * FROM devices WHERE store_id = x

这查询列表中具有特定 store_id 的部分。索引对于此查询有效,但可能有点臃肿;仅对 store_id 建立索引可能更有效。

SELECT * FROM devices WHERE store_id = x, time > 10

此查询无效,因为它需要扫描列表的多个部分。这是因为包含一个设备的 time > 10 数据的列表部分将位于与不同设备不同的部分。在这种情况下,请考虑改为在 (store_id, time) 上构建索引。

SELECT * FROM devices WHERE device_id = M, time > 10

示例中的索引对于此查询无用,因为每个 store_iddevice M 数据都位于列表的完全不同的部分。

SELECT * FROM devices WHERE store_id = M, device_id = M, time > 10

对于此索引,这是一个准确的查询。它将列表缩小到非常特定的部分。

关键词

在此页面上发现问题?报告问题 或 在 GitHub 上编辑此页