【问题标题】:How to optimize the following query by adding more indexes?如何通过添加更多索引来优化以下查询?
【发布时间】:2021-12-07 12:57:51
【问题描述】:

我正在尝试优化一直在破坏我的数据库的查询。

https://explain.depesz.com/s/isM1

如果您对如何改善这一点有任何见解,请告诉我。

我们使用的是 RDS/Postgres 11.9

explain analyze SELECT "src_rowdifference"."key",
       "src_rowdifference"."port_id",
       "src_rowdifference"."shipping_line_id",
       "src_rowdifference"."container_type_id",
       "src_rowdifference"."shift_id",
       "src_rowdifference"."prev_availability_id",
       "src_rowdifference"."new_availability_id",
       "src_rowdifference"."date",
       "src_rowdifference"."prev_last_update",
       "src_rowdifference"."new_last_update"
FROM "src_rowdifference"
INNER JOIN "src_containertype" ON ("src_rowdifference"."container_type_id" = "src_containertype"."key")
WHERE ("src_rowdifference"."container_type_id" IN
         (SELECT U0."key"
          FROM "src_containertype" U0
          INNER JOIN "notification_tablenotification_container_types" U1 ON (U0."key" = U1."containertype_id")
          WHERE U1."tablenotification_id" = 'test@test.com')
       AND "src_rowdifference"."new_last_update" >= '2020-01-15T03:11:06.291947+00:00'::timestamptz
       AND "src_rowdifference"."port_id" IN
         (SELECT U0."key"
          FROM "src_port" U0
          INNER JOIN "notification_tablenotification_ports" U1 ON (U0."key" = U1."port_id")
          WHERE U1."tablenotification_id" = 'test@test.com')
       AND "src_rowdifference"."shipping_line_id" IN
         (SELECT U0."key"
          FROM "src_shippingline" U0
          INNER JOIN "notification_tablenotification_shipping_lines" U1 ON (U0."key" = U1."shippingline_id")
          WHERE U1."tablenotification_id" = 'test@test.com')
       AND "src_rowdifference"."prev_last_update" IS NOT NULL
       AND NOT ("src_rowdifference"."prev_availability_id" = 'na'
                AND "src_rowdifference"."prev_availability_id" IS NOT NULL)
       AND NOT ("src_rowdifference"."key" IN
                  (SELECT V1."rowdifference_id"
                   FROM "notification_tablenotificationtrigger_row_differences" V1
                   WHERE V1."tablenotificationtrigger_id" IN
                       (SELECT U0."id"
                        FROM "notification_tablenotificationtrigger" U0
                        WHERE U0."notification_id" = 'test@test.com'))));

我所有的索引都是 btree + btree(varchar_pattern_ops) "src_rowdifference_port_id_shipping_line_id_9b3465fc_uniq" 唯一约束,btree (port_id, shipping_line_id, container_type_id, shift_id, date, new_last_update)

编辑:我所做的一点不相关的更改是为我的 RDS 实例添加了更多的 ssd 磁盘空间。这对 CPU 使用率产生了巨大影响,进而对我们拥有的连接数量产生了巨大影响。

【问题讨论】:

  • 对 WHERE 子句中的所有子查询使用适当的索引。
  • @jjanes 我已经添加了索引类型。

标签: postgresql query-optimization amazon-rds


【解决方案1】:

很难从整体上考虑这个计划,因为我不明白它在寻找什么。但从各个部分来看,有两个部分共同主导了运行时间。

一个是对 src_rowdifference_port_id_shipping_line_id_9b3465fc 的索引扫描,考虑到返回的行数,这似乎相当慢。将索引条件与索引列进行比较,我可以看到 new_last_update 上的条件无法在索引中有效应用,因为索引中的两列在它之前并且在节点中没有相等条件。因此,>= 被用作“索引内过滤器”,它需要测试每一行并拒绝它,而不是批量跳过它。我不知道删除了多少行,因为“过滤器删除的行”不计入索引过滤器,但它可能很大。所以要尝试的一件事是在(port_id, shipping_line_id, container_type_id, new_last_update) 上创建一个新索引。或者也许用重新排序的版本(port_id, shipping_line_id, container_type_id, new_last_update, shift_id, date) 替换该索引,但当然这可能会使其他查询变得更糟。

另一个耗时的事情是将物化节点踢 47000 次(每次循环多达 22000 行)以实现NOT (SubPlan 1)。那应该使用散列子计划,而不是线性搜索子计划。我能想到它不执行散列子计划的唯一原因是 work_mem 不够大,无法预期将其放入内存中。你对 work_mem 的设置是什么?如果将其增加到“100MB”左右会发生什么?

EXPLAIN 中的NOT (SubPlan 1) 对应于您的查询部分AND NOT ("src_rowdifference"."key" IN (...))。如果增加 work_mem 不起作用,您可以尝试将其重写为 NOT EXISTS 子句。

【讨论】:

    猜你喜欢
    • 2023-03-15
    • 2014-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-31
    • 1970-01-01
    • 1970-01-01
    • 2012-08-21
    相关资源
    最近更新 更多