【发布时间】: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