>> * Eventually, we should cache the number of blocks in a relation somewhere.
>> * Until that time, this code will have to do an lseek to determine the number
>> * of blocks in a relation.
>>
>> As far as I can see there's field rd_nblocks in Relation.
>>
>> Question: is this field properly updated?
No. If it were that easy, this problem would have been fixed long ago.
The problem with the relcache field is that it's backend-local, so it's
not going to get updated when some other backend extends the relation.
We do use rd_nblocks to cache the last table length determined from
lseek, but that can't be trusted in critical cases, like when we are
trying to add a block to the relation.
There has been some talk of keeping a small cache of current relation
lengths in shared memory, but I'm dubious that that'd actually be a win.
In order to save an lseek (which ought to be pretty quick as kernel
calls go) we'd be talking about grabbing a spinlock, searching a shared
hashtable, and releasing a spinlock. Spinlock contention on this
heavily used datastructure might well be a problem. Now add the costs
of updating that hashtable every time we extend a relation (or even just
fail to find a relation in it). Not immediately obvious that this is
a net win overall, is it? If it were easier to do, or more obviously
a large performance gain, someone would likely have tried it by now ...
but there is lots of lower-hanging fruit to keep us busy.
regards, tom lane