On 1/16/21 4:11 PM, Anastasia Lubennikova wrote:

> ...

As Pavan correctly figured it out before the problem is that RelationGetBufferForTuple() moves to the next page, losing free space in the block:

 > ... I see that a relcache invalidation arrives
 > after 1st and then after every 32672th block is filled. That clears the
 > rel->rd_smgr field and we lose the information about the saved target
> block. The code then moves to extend the relation again and thus skips the > previously less-than-half filled block, losing the free space in that block.

The reason of this cache invalidation is vm_extend() call, which happens every 32762 blocks.

RelationGetBufferForTuple() tries to use the last page, but for some reason this code is under 'use_fsm' check. And COPY FROM doesn't use fsm (see TABLE_INSERT_SKIP_FSM).


         /*
         * If the FSM knows nothing of the rel, try the last page before we          * give up and extend.  This avoids one-tuple-per-page syndrome during
          * bootstrapping or in a recently-started system.
          */
         if (targetBlock == InvalidBlockNumber)
         {
             BlockNumber nblocks = RelationGetNumberOfBlocks(relation);
             if (nblocks > 0)
                 targetBlock = nblocks - 1;
         }


I think we can use this code without regard to 'use_fsm'. With this change, the number of toast rel pages is correct. The patch is attached.


Thanks for the updated patch, this version looks OK to me - I've marked it as RFC. I'll do a bit more testing, review, and then I'll get it committed.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Reply via email to