>From: Chao Li <[email protected]>
>Date: 2026-05-15 16:34
>To: Postgres hackers <[email protected]>
>Subject: Re: Adjust pg_stat_get_lock() prorows to match lock types
>
>
>
>> On May 4, 2026, at 10:23, Chao Li <[email protected]> wrote:
>>
>> Hi,
>>
>> I read the code of pg_stat_lock() and played a bit with it. I happened to notice one thing: the function always returns 12 rows, but the planner estimates 10 rows:
>>
>> ```
>> evantest=# EXPLAIN ANALYZE SELECT * FROM pg_catalog.pg_stat_lock;
>> QUERY PLAN
>> -----------------------------------------------------------------------------------------------------------------------
>> Function Scan on pg_stat_get_lock l (cost=0.00..0.10 rows=10 width=64) (actual time=0.067..0.071 rows=12.00 loops=1)
>> Planning Time: 0.121 ms
>> Execution Time: 0.126 ms
>> (3 rows)
>> ```
>>
>> Then I found that, in pg_proc.dat, the function's prorows is defined as 10. Since the function returns one row per lock type, and lock types are not something that change frequently, I think it is better to give the planner a more accurate row count. After changing prorows to 12, the plan looks like this:
>>
>> ```
>> evantest=# EXPLAIN ANALYZE SELECT * FROM pg_catalog.pg_stat_lock;
>> QUERY PLAN
>> -----------------------------------------------------------------------------------------------------------------------
>> Function Scan on pg_stat_get_lock l (cost=0.00..0.12 rows=12 width=64) (actual time=0.134..0.138 rows=12.00 loops=1)
>> Planning:
>> Buffers: shared hit=13
>> Planning Time: 0.313 ms
>> Execution Time: 0.228 ms
>> (5 rows)
>> ```
>>
>> While there, I also made two small tweaks to two function comments in pgstat_lock.c. If those are not considered worth changing, I am okay with removing them from the patch.
>>
>> Please see the attached patch for details.
>>
>> Best regards,
>> --
>> Chao Li (Evan)
>> HighGo Software Co., Ltd.
>> https://www.highgo.com/
>>
>>
>>
>>
>> <v1-0001-Adjust-pg_stat_get_lock-row-estimate-and-comments.patch>
>
>Rebased.
>
>Best regards,
>--
>Chao Li (Evan)
>HighGo Software Co., Ltd.
>https://www.highgo.com/
Hi Chao,
After testing with GDB, I found that before your patch, the catalog data of
pg_stat_get_lock shows (proowner = 10):
{oid = 6509, proname = {data = "pg_stat_get_lock", '\000' <repeats 47
times>}, pronamespace = 11, proowner = 10, prolang = 12, procost = 1,
prorows = 10, provariadic = 0, prosupport = 0, prokind = 102 'f', prosecdef =
false, proleakproof = false, proisstrict = true, proretset = true, provolatile
= 118 'v', proparallel = 114 'r', pronargs = 0, pronargdefaults = 0, prorettype
= 2249, proargtypes = {vl_len_ = 96, ndim = 1, dataoffset = 0, elemtype = 26,
dim1 = 0, lbound1 = 0, values = 0x7f09190754e0}}
`
With your v2 patch applied, the data becomes (proowner = 12):
{oid = 6509, proname = {data = "pg_stat_get_lock", '\000' <repeats 47
times>}, pronamespace = 11, proowner = 10, prolang = 12, procost = 1,
prorows = 12, provariadic = 0, prosupport = 0, prokind = 102 'f',
prosecdef = false, proleakproof = false, proisstrict = true, proretset = true,
provolatile = 118 'v', proparallel = 114 'r', pronargs = 0,
pronargdefaults = 0, prorettype = 2249, proargtypes = {vl_len_ = 96, ndim = 1,
dataoffset = 0, elemtype = 26, dim1 = 0, lbound1 = 0, values =
0x7f013c201788}}
`
The estimated row count 12 of pg_stat_get_lock matches the number of lockable
object types:
relation, extend, frozenid, page, tuple, transactionid, virtualxid, spectoken,
object, userlock, advisory, and applytransaction.
This is exactly as mentioned in the documentation "Table 27.11. Wait Events of
Type Lock", as shown below.
`
xman=# explain select * from pg_catalog.pg_stat_lock;
QUERY PLAN
-------------------------------------------------------------------------
Function Scan on pg_stat_get_lock l (cost=0.00..0.12 rows=12
width=64)
(1 row)
xman=# explain analyze select * from pg_catalog.pg_stat_lock;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
Function Scan on pg_stat_get_lock l (cost=0.00..0.12 rows=12
width=64) (actual time=0.115..0.124 rows=12.00 loops=1)
Planning Time: 4941.026 ms
Execution Time: 0.240 ms
(3 rows)
xman=# select * from pg_catalog.pg_stat_lock;
locktype | waits | wait_time |
fastpath_exceeded | stats_reset
------------------+-------+-----------+-------------------+-------------------------------
relation | 0 |
0 | 0 |
2026-06-06 10:59:06.350828+08
extend | 0 |
0 |
0 | 2026-06-06 10:59:06.350828+08
frozenid | 0 |
0 | 0 |
2026-06-06 10:59:06.350828+08
page | 0 |
0 |
0 | 2026-06-06 10:59:06.350828+08
tuple | 0 |
0 |
0 | 2026-06-06 10:59:06.350828+08
transactionid | 0 |
0 | 0 |
2026-06-06 10:59:06.350828+08
virtualxid | 0 |
0 | 0 |
2026-06-06 10:59:06.350828+08
spectoken | 0 |
0 | 0 |
2026-06-06 10:59:06.350828+08
object | 0 |
0 |
0 | 2026-06-06 10:59:06.350828+08
userlock | 0 |
0 | 0 |
2026-06-06 10:59:06.350828+08
advisory | 0 |
0 | 0 |
2026-06-06 10:59:06.350828+08
applytransaction | 0 | 0 |
0 | 2026-06-06
10:59:06.350828+08
(12 rows)
`
Thanks for the patch.
regards,
--
ZizhuanLiu (X-MAN)
[email protected]