Cache last known per-tuple offsets to speed long tuple accessを実装したときのメモ

カラム数が多いテーブルをjoinするとき,heaptuple.cのnocachegetattr()に負荷がかかる。
390行目付近のfor()ループで,カラムの先頭から調べてるので,カラム数が多いほど負荷が高くなる。

ExecProject() -> ExecTargetList() -> ExecEvalExpr() -> ExecEvalVar() -> nocachegetattr()

TupleTableSlotにheap_deformtupleした結果をキャッシュすることはできないか?

・TupleTableSlotに,heap_deform用のメンバを追加。
  追加するメンバは,values, nulls, データが有効かどうかのフラグ。
・ExecAllocTableSlot(), MakeTupleTableSlot()に新しいメンバを初期化する処理を追加
  (初期化処理は共通関数にする)
・ExecClearTuple()で,フラグをクリアする。
・ExecDropTupleTable()で,values, nullsのメモリを開放する。
・ExecEvalVar()でカラム数が多い場合は,heap_deformtupleを使う。

検討事項
・どこでvalues, nullsのメモリを確保するか
・ExecEvalVarでheap_deformtupleを使う条件
include/access/htup.h
 struct DeformTupleStateの追加
 InitDeformTupleStateマクロの追加
 CheckDeformTupleExtractedマクロの追加

backend/access/common/heaptuple.c
 heap_deformtuple_incr()の追加
 heap_deformtuple()の変更

include/access/heapam.h
 heap_deformtuple_incr()の宣言を追加

include/executor/tuptable.h
 TupleTableSlot構造体を拡張
 TupleTableData構造体を拡張

backend/executor/execTuples.c
 ExecFreeSlotDeformCache()を追加
 ExecAllocSlotDeformCache()を追加

 ExecSetSlotDescriptor()で,cacheメモリの開放/アロケート処理を追加
 ExecDropTupleTable()で,cacheメモリの開放処理を追加

 InitTupleTableSlot()を追加(code cleanup)
 ExecAllocTableSlot()とMakeTupleTableSlot()で,InitTupleTableSlot()を利用する

 ExecCreateTupleTable()で,MemoryContextを保存
 ExecClearTuple()で,DeformTupleStateをリセットする処理を追加

include/executor/executor.h
 DeformTupleCacheIsValidマクロを追加

backend/executor/execQual.c
 ExecEvalVar()でdeform_cacheが利用できるときは,heap_deformtuple_range()を使うように変更。
test data
---------
 15,000 rows, 200 column
 data type: text

select t100, t110, t120, t130, t140, t150, t160, t170, t180, t190, t200
from aaa

original
----------
Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total
 time   seconds   seconds    calls   s/call   s/call  name
 70.05      1.31     1.31   163846     0.00     0.00  nocachegetattr
  8.02      1.46     0.15   163840     0.00     0.00  FunctionCall3
  1.87      1.50     0.04   397763     0.00     0.00  AllocSetFreeIndex
  1.60      1.52     0.03   163840     0.00     0.00  ExecEvalVar
  1.34      1.55     0.03   200414     0.00     0.00  AllocSetAlloc

  total time is 1.87 sec.
  
patched
----------  
Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
 39.73      0.29     0.29   180224     0.00     0.00  heap_deformtuple_incr
  9.59      0.36     0.07   163840     0.00     0.00  FunctionCall3
  6.85      0.41     0.05    16384     0.00     0.02  ExecTargetList
  5.48      0.45     0.04    23477     0.00     0.00  hash_any
  4.11      0.48     0.03   200414     0.00     0.00  AllocSetAlloc
  
  total time is 0.73 sec.

最終的にはheap_deformtupleの拡張ではなく、slot_deformtupleという関数が追加された。