Postgresql 获取一列或大表中一组唯一值的最快方法

2023-12-24

我在 Postgresql 数据库中有一个不断增长的、可能非常大的表,其中包含来自不同“设备”的不同“通道”的“数据”,例如:

Table data:
  id (PK)
  device_id (FK -> device)
  channel_id (FK -> channel)
  timestamp (TIMESTAMP)
  value (Float)

我使用分区将表分成多个子表,每个子表对应一个设备,因为我从不需要在同一查询中不同设备的数据。由于并非所有设备都提供所有频道,因此我想获取单个设备的所有可用频道的列表。解决我的问题的一个简单的 SQL 查询是:

SELECT DISTINCT(channel_id) FROM data where device_id = 1;

这工作得很好,但对于数据表中有很多条目的设备来说需要很长时间。使用分区大大加快了这一过程,因为数据库只需检查一个设备的条目,但对于某些设备来说仍然需要很长时间才能完成。

我的应用程序的属性使得为一台设备添加新通道类型的情况很少发生。大多数情况下,设备添加到数据库后频道会很快添加,之后不会再添加新频道。然而,可用通道的数据添加得相当频繁。我还需要经常向用户显示每个设备的可用频道列表,因此希望加快可用频道的查找速度。我已经在channel_ids上有一个索引,希望它能加快获取所需列表的速度,但检索列表仍然需要相当长的时间。

目前,我可以想出几种方法来解决我的问题:

  1. 使用 postgres 的一些“神奇”功能,它完全符合我的要求,但我对此一无所知。
  2. 使用触发器来维护某种类型的额外表,每个“设备”/“通道”组合仅包含一个条目,因此允许快速访问可用通道。然而,由于新数据经常插入,我想触发器会产生相当多的开销,而它只在极少数情况下检测新通道。
  3. 重新考虑我的数据库设计。也许插入另一个包含“通道”和“设备”之间的链接的表,然后只在该表的“数据”中拥有一个 FK。中间表上的查询应该很快,但是,这基本上增加了将数据插入数据库的应用程序的复杂性。
  4. 也许视图可以在这里提供帮助?
  5. 在我的前端中使用缓冲仅定期执行查询,因为可用通道不会经常更改。

在我看来,第 2 点和第 3 点似乎会增加很多不必要的开销,我想避免这些开销。由于我没有找到与此主题相关的任何内容,因此我目前认为解决方案 5. 是我要采用的方法。但是,我想知道是否有人对我的问题有更好的、可能基于数据库的解决方案。

感谢您的帮助。


对于选项 1,您要做的是“松散索引扫描”或“跳过扫描”。

如果 PostgreSQL 能够在有益的时候自动执行这些操作,那就太好了,但到目前为止它还没有这样做。但是你可以把它骗进去。 http://wiki.postgresql.org/wiki/Loose_indexscan我从未在分区表上尝试过此操作,但我认为向 union all 的每个分支添加合适的 WHERE 子句会很简单。

也许您也想要选项 3,或者相反,我没有足够的信息可以说。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Postgresql 获取一列或大表中一组唯一值的最快方法 的相关文章

随机推荐