我使用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毫秒。Time作为参数提供,用于执行此查询,它包含epoch秒和微秒。
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;
现在这个可能也会降级,也可能不会降级,也可能会降级,但仍然很快,这无关紧要。