因为查找数据可能需要很长时间,特别是如果您的超表中有大量数据,所以您可以使用索引来加速从非压缩块(它们使用自己的列式索引)读取操作。
您可以在列的任意组合上创建索引。要将索引定义为 UNIQUE
或 PRIMARY KEY
索引,它必须包含分区列(这通常是时间列)。
您选择在其上创建索引的列取决于您存储的数据类型。当您创建超表时,将 time
列的数据类型设置为 timestamptz
而不是 timestamp
。有关更多信息,请参阅 PostgreSQL 时间戳。
注意
虽然可以添加不包含 time
列的索引,但这样做会导致非常慢的摄取速度。对于时序数据,在时间列上建立索引允许每个块创建一个索引。
考虑一个简单的示例,其中收集了来自两个位置(名为 office
和 garage
)的温度
(location, time DESC)
上的索引像这样组织
garage-0940garage-0930garage-0920garage-0910office-0930office-0920office-0910
(time DESC, location)
上的索引像这样组织
0940-garage0930-garage0930-office0920-garage0920-office0910-garage0910-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_id
和 store_id
上添加另一个索引。这将创建一个复合索引。(store_id, device_id, time)
上的复合索引首先按 store_id
排序。每个唯一的 store_id
,然后将按 device_id
顺序排序。并且每个具有相同 store_id
和 device_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_id
的 device M
数据都位于列表的完全不同的部分。
SELECT * FROM devices WHERE store_id = M, device_id = M, time > 10
对于此索引,这是一个准确的查询。它将列表缩小到非常特定的部分。
关键词
在此页面上发现问题?报告问题 或 在 GitHub 上编辑此页。