[英]Postgres query taking long to execute
我正在使用 libpq 在 C++ 代码中连接 Postgres 服务器。 Postgres 服务器版本为 12.10
我的表模式定义如下
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
---------------------+----------+-----------+----------+------------+----------+--------------+-------------
event_id | bigint | | not null | | plain | |
event_sec | integer | | not null | | plain | |
event_usec | integer | | not null | | plain | |
event_op | smallint | | not null | | plain | |
rd | bigint | | not null | | plain | |
addr | bigint | | not null | | plain | |
masklen | bigint | | not null | | plain | |
path_id | bigint | | | | plain | |
attribs_tbl_last_id | bigint | | not null | | plain | |
attribs_tbl_next_id | bigint | | not null | | plain | |
bgp_id | bigint | | not null | | plain | |
last_lbl_stk | bytea | | not null | | extended | |
next_lbl_stk | bytea | | not null | | extended | |
last_state | smallint | | | | plain | |
next_state | smallint | | | | plain | |
pkey | integer | | not null | 1654449420 | plain | |
Partition key: LIST (pkey)
Indexes:
"event_pkey" PRIMARY KEY, btree (event_id, pkey)
"event_event_sec_event_usec_idx" btree (event_sec, event_usec)
Partitions: event_spl_1651768781 FOR VALUES IN (1651768781),
event_spl_1652029140 FOR VALUES IN (1652029140),
event_spl_1652633760 FOR VALUES IN (1652633760),
event_spl_1653372439 FOR VALUES IN (1653372439),
event_spl_1653786420 FOR VALUES IN (1653786420),
event_spl_1654449420 FOR VALUES IN (1654449420)
当我执行以下查询时,执行需要 1 - 2 毫秒。 时间作为参数提供给执行此查询的函数,它包含纪元秒和微秒。
SELECT event_id FROM event WHERE (event_sec > time.seconds) OR ((event_sec=time.seconds) AND (event_usec>=time.useconds) ORDER BY event_sec, event_usec LIMIT 1
此查询在同一客户端连接上每 30 秒执行一次(持续数周)。 此过程会运行数周,但有时同一查询开始需要超过 10 分钟。
如果我重新启动该过程,它会重新创建与服务器的连接,现在执行时间再次回落到 1-2 毫秒。 此问题是间歇性的,有时会在运行一周后触发,有时会在运行 2-3 周后触发。
我们每周日在表中添加一个新分区,并在新分区中写入新数据。
我不知道为什么性能不一致,有很多可能性我们无法通过提供的信息来区分。 例如,当性能发生变化时,计划是否会发生变化,或者相同的计划是否会变得更糟?
但是您的查询并不是为了最大限度地利用索引而编写的。 在我手中,它可以使用索引进行排序,但是它仍然需要读取并单独跳过 WHERE 子句失败的内容,直到找到第一个通过的内容。 而且由于分区,我认为它甚至比这更糟糕,它必须执行此读取和跳过操作,直到找到每个分区中通过的第一个。
你可以重写它来做一个元组比较,它可以使用索引来确定顺序和从哪里开始:
SELECT event_id FROM event
WHERE (event_sec,event_sec) >= (:seconds,:useconds)
ORDER BY event_sec, event_usec LIMIT 1;
现在这也可能会降级,也可能不会降级,或者可能会降级但仍然如此之快,这无关紧要。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.