>From: Chao Li <li.evan.chao@gmail.com>
>Date: 2026-05-15 16:34
>To: Postgres hackers <pgsql-hackers@lists.postgresql.org>
>Subject: Re: Adjust pg_stat_get_lock() prorows to match lock types
>
>
>
>> On May 4, 2026, at 10:23, Chao Li <li.evan.chao@gmail.com> 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) 
44973863@qq.com