Tom Lane wrote:
> Heikki Linnakangas <heikki.linnakangas@enterprisedb.com> writes:
>> The visibility map won't be inquired unless you vacuum. This is a bit
>> tricky. In vacuum, we only know whether we can set a bit or not, after
>> we've acquired a cleanup lock on the page, and scanned all the tuples.
>> While we're holding a cleanup lock, we don't want to do I/O, which could
>> potentially block out other processes for a long time. So it's too late
>> to extend the visibility map at that point.
>
> This is no good; I think you've made the wrong tradeoffs. In
> particular, even though only vacuum *currently* uses the map, you want
> to extend it to be used by indexscans. So it's going to uselessly
> spring into being even without vacuums.
>
> I'm not convinced that I/O while holding cleanup lock is so bad that we
> should break other aspects of the system to avoid it. However, if you
> want to stick to that, how about
> * vacuum page, possibly set its header bit
> * release page lock (but not pin)
> * if we need to set the bit, fetch the corresponding map page
> (I/O might happen here)
> * get share lock on heap page, then recheck its header bit;
> if still set, set the map bit
Yeah, could do that.
There is another problem, though, if the map is frequently probed for
pages that don't exist in the map, or the map doesn't exist at all.
Currently, the size of the map file is kept in relcache, in the
rd_vm_nblocks_cache variable. Whenever a page is accessed that's >
rd_vm_nblocks_cache, smgrnblocks is called to see if the page exists,
and rd_vm_nblocks_cache is updated. That means that every probe to a
non-existing page causes an lseek(), which isn't free.
-- Heikki Linnakangas EnterpriseDB http://www.enterprisedb.com