【问题标题】:Postgres - most efficient way to retrieve most recent record from a groupPostgres - 从组中检索最新记录的最有效方法
【发布时间】:2021-09-25 05:29:23
【问题描述】:

我们有一张表,其中记录了已发生的作业执行日志。该表可能会变得非常大(例如 100M+ 行),尽管我们当然可以定期修剪尾部以使其保持较小(例如

我们希望找到一个合理的最佳查询,可以找到每种作业类型的最后一次执行。作业以不同的频率运行;有些是每秒一次,有些是每周一次。我们要跟踪数百种“类型”的作业(一旦考虑到独特的配置。)

我们想到了几个选项:

选项 1) 使用触发器 upsert 到 most_recent_execution 表,在 job_configuration_id 上使用 on conflict 覆盖相同 id 的记录。好处:这将是一张只有几百行的小桌子;缺点:桌子上需要大量的膨胀(和吸尘),因为会有很多更新。

选项 2) 主日志表上的 BRIN 索引,按 execution_date/id。好处:只能在同一张桌子上工作。缺点:我们不了解多列 BRIN 索引的语义。

选项 3) 主日志表上的条件索引,它使用工作已知频率的某个倍数作为索引记录的日期范围限制。缺点:可能会与查询规划器搏斗。

选项4)主日志表上的条件索引,它使用窗口函数将每种类型的排名靠前的记录包含在索引中。缺点:再次,可能与查询规划器搏斗。

我们当然会进行原型设计和基准测试,但如果有人做过类似的工作,我们欢迎您提出想法。

【问题讨论】:

  • 表定义?是否归一化为 3NF?它有多个候选键吗?
  • 不是一个完整的答案,但如果您使用触发器并将自己限制为更新类型的索引,那么如果您为该小表选择合理的fill_factor,HOT 应该会大大减少膨胀。
  • 仅对您的时间戳和工作类型进行索引有什么问题?您向我们展示了几个(复杂的)选项,但缺少最简单的选项。选择结果的 SELECT 语句中的 EXPLAIN(ANALYZE, VERBOSE) 也缺失。
  • @RichardHuxton 谢谢,我们将结合触发方法来查看 HOT 更新 - 不知道它们。 (cybertec-postgresql.com/en/…)
  • 您是否有一个简洁的作业类型列表(例如,在一个包含 FK 的较小表中),还是需要从大表本身推断出来?

标签: sql postgresql query-optimization


【解决方案1】:

按时间范围对日志表进行分区。在最后几个分区的(job_type, execution_time) 上有一个 b 树索引。使用WHERE job_type = 42 ORDER BY execution_time DESC LIMIT 1 获取最后几个分区上查询的UNION 并获取最新的。

那应该像闪电一样快,避免大索引。缺点:每个INSERT 的索引维护成本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-13
    • 2013-09-05
    • 2013-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多