Thread: Inefficiency in InitIndexFreeSpaceMap

Inefficiency in InitIndexFreeSpaceMap

From
Tom Lane
Date:
Why is InitIndexFreeSpaceMap coded to test for the FSM file already
existing?  AFAICS it cannot yet exist and it should be an error anyway
if it does.  The smgrexists probe is hardly free, so losing it would be
good.
        regards, tom lane


Re: Inefficiency in InitIndexFreeSpaceMap

From
Heikki Linnakangas
Date:
Tom Lane wrote:
> Why is InitIndexFreeSpaceMap coded to test for the FSM file already
> existing?  AFAICS it cannot yet exist and it should be an error anyway
> if it does.

Hmm. The FSM file can exist, if the index isn't created anew, but
truncated and rebuilt. However, we normally create a new relfilenode in
that case, so the only place where that actually happens is with a
temporary ON COMMIT DELETE ROWS table. We could instead drop any extra
relforks when the main fork is truncated, and let index_build recreate
the FSM, see attached patch. That approach does seem cleaner to me, but
it's actually even worse from a performance point of view, FWIW, because
instead of just truncating the file, it's unlinked and recreated.

>  The smgrexists probe is hardly free, so losing it would be
> good.

Well, it's only done in index build, so I'm not too worried.

--
   Heikki Linnakangas
   EnterpriseDB   http://www.enterprisedb.com
*** src/backend/catalog/heap.c
--- src/backend/catalog/heap.c
***************
*** 2257,2262 **** RelationTruncateIndexes(Relation heapRelation)
--- 2257,2263 ----
          Oid            indexId = lfirst_oid(indlist);
          Relation    currentIndex;
          IndexInfo  *indexInfo;
+         ForkNumber forknum;

          /* Open the index relation; use exclusive lock, just to be sure */
          currentIndex = index_open(indexId, AccessExclusiveLock);
***************
*** 2265,2275 **** RelationTruncateIndexes(Relation heapRelation)
          indexInfo = BuildIndexInfo(currentIndex);

          /*
!          * Now truncate the actual file (and discard buffers). The indexam
!          * is responsible for truncating the FSM in index_build(), if
!          * applicable.
           */
          RelationTruncate(currentIndex, 0);

          /* Initialize the index and rebuild */
          /* Note: we do not need to re-establish pkey setting */
--- 2266,2280 ----
          indexInfo = BuildIndexInfo(currentIndex);

          /*
!          * Now truncate the actual file (and discard buffers), and drop any
!          * additional forks. This leaves us in the same state as after
!          * heap_create().
           */
          RelationTruncate(currentIndex, 0);
+         for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
+             if (smgrexists(currentIndex->rd_smgr, forknum))
+                 smgrdounlink(currentIndex->rd_smgr, forknum,
+                              currentIndex->rd_istemp, false);

          /* Initialize the index and rebuild */
          /* Note: we do not need to re-establish pkey setting */
*** src/backend/storage/freespace/indexfsm.c
--- src/backend/storage/freespace/indexfsm.c
***************
*** 38,47 **** InitIndexFreeSpaceMap(Relation rel)
  {
      /* Create FSM fork if it doesn't exist yet, or truncate it if it does */
      RelationOpenSmgr(rel);
!     if (!smgrexists(rel->rd_smgr, FSM_FORKNUM))
!         smgrcreate(rel->rd_smgr, FSM_FORKNUM, rel->rd_istemp, false);
!     else
!         smgrtruncate(rel->rd_smgr, FSM_FORKNUM, 0, rel->rd_istemp);
  }

  /*
--- 38,44 ----
  {
      /* Create FSM fork if it doesn't exist yet, or truncate it if it does */
      RelationOpenSmgr(rel);
!     smgrcreate(rel->rd_smgr, FSM_FORKNUM, rel->rd_istemp, false);
  }

  /*

Re: Inefficiency in InitIndexFreeSpaceMap

From
Tom Lane
Date:
Heikki Linnakangas <heikki.linnakangas@enterprisedb.com> writes:
> Tom Lane wrote:
>> Why is InitIndexFreeSpaceMap coded to test for the FSM file already
>> existing?  AFAICS it cannot yet exist and it should be an error anyway
>> if it does.

> Hmm. The FSM file can exist, if the index isn't created anew, but 
> truncated and rebuilt. However, we normally create a new relfilenode in 
> that case, so the only place where that actually happens is with a 
> temporary ON COMMIT DELETE ROWS table.

Hm.  I would say that the brokenness in RelationTruncateIndexes is that
it truncates the main fork and not the others.  This is unlike other
places that do such things.

>> The smgrexists probe is hardly free, so losing it would be
>> good.

> Well, it's only done in index build, so I'm not too worried.

See Kevin Grittner's gripe about the speed of temp table creation.
I'm already worried that the FSM changes will have a huge negative
impact on that.  Adding extra filesystem operations that don't have
to be there doesn't help.
        regards, tom lane