可扩展哈希表和几个数据结构有关,一个是HCTL,这个是创建可扩展哈希表时的信息表,一个是HTAB,这个就是哈希表结构,一个是HASHHDR,这个是哈希表头结构,包含了哈希表的所有可变信息,还有HashSegment、HashBucket、HashElement等结构,一个HashSegment是HashBucket数组的头,一个HashBucket是HashElement链表。结构定义见下面。这些结构和起来组成了可扩展哈希表。根据pg默认参数创建的可扩展哈希表结构图在下面。
typedef struct HASHCTL
{
long num_partitions;/* # partitions (must be power of 2) */
long ssize; /* segmentsize */
long dsize; /* (initial)directory size */
long max_dsize; /* limit todsize if dir size is limited */
long ffactor; /* fill factor*/
Size keysize; /* hash key length in bytes */
Size entrysize; /* total user element size in bytes*/
HashValueFunc hash; /* hashfunction */
HashCompareFuncmatch; /*key comparison function */
HashCopyFunckeycopy; /*key copying function */
HashAllocFunc alloc; /* memoryallocator */
MemoryContext hcxt; /* memorycontext to use for allocations */
HASHHDR *hctl; /* location of header in shared mem */
} HASHCTL;
struct HTAB
{
HASHHDR *hctl; /* => shared control information */
HASHSEGMENT*dir; /*directory of segment starts */
HashValueFunchash; /*hash function */
HashCompareFuncmatch; /*key comparison function */
HashCopyFunckeycopy; /*key copying function */
HashAllocFuncalloc; /*memory allocator */
MemoryContexthcxt; /*memory context if default allocator used */
char *tabname; /* table name (for error messages) */
bool isshared; /* true iftable is in shared memory */
/* We keep local copies of these fixed values to reducecontention */
Size keysize; /* hash key length in bytes */
long ssize; /* segment size ---must be power of 2 */
int sshift; /* segment shift =log2(ssize) */
};
struct HASHHDR
{
/* In a partitioned table, take this lock to touch nentriesor freeList */
slock_t mutex; /* unused if not partitioned table */
/* These fields change during entry addition/deletion */
long nentries; /* number ofentries in hash table */
HASHELEMENT*freeList; /*linked list of free elements */
/* These fields can change, but not in a partitioned table*/
/* Also, dsize can't change in a shared table, even ifunpartitioned */
long dsize; /* directorysize */
long nsegs; /* number ofallocated segments (<= dsize) */
uint32 max_bucket; /* ID of maximum bucket in use */
uint32 high_mask; /* mask to modulo into entire table */
uint32 low_mask; /* mask to modulo into lower half of table */
/* These fields are fixed at hashtable creation */
Size keysize; /* hash keylength in bytes */
Size entrysize; /* total user element size in bytes*/
long num_partitions;/* # partitions (must be power of 2), or 0 */
long ffactor; /* target fillfactor */
long max_dsize; /* 'dsize' limitif directory is fixed size */
long ssize; /* segmentsize --- must be power of 2 */
int sshift; /* segmentshift = log2(ssize) */
int nelem_alloc; /* number ofentries to allocate at once */
#ifdef HASH_STATISTICS
/*
* Count statisticshere. NB: stats code doesn't bother withmutex, so
* counts could becorrupted a bit in a partitioned table.
*/
long accesses;
long collisions;
#endif
};