diff --git a/src/backend/access/hash/hashsort.c b/src/backend/access/hash/hashsort.c index aa61e39f26..fa177272d3 100644 --- a/src/backend/access/hash/hashsort.c +++ b/src/backend/access/hash/hashsort.c @@ -42,9 +42,10 @@ struct HSpool Relation index; /* - * We sort the hash keys based on the buckets they belong to. Below masks - * are used in _hash_hashkey2bucket to determine the bucket of given hash - * key. + * We sort the hash keys based on the buckets they belong to, then by + * the hash values themselves, to optimize the insertion onto hash pages. + * The masks below are used in _hash_hashkey2bucket to determine the + * bucket of a given hash key. */ uint32 high_mask; uint32 low_mask; diff --git a/src/backend/utils/sort/tuplesortvariants.c b/src/backend/utils/sort/tuplesortvariants.c index 2933020dcc..61912a25f0 100644 --- a/src/backend/utils/sort/tuplesortvariants.c +++ b/src/backend/utils/sort/tuplesortvariants.c @@ -1387,6 +1387,8 @@ comparetup_index_hash(const SortTuple *a, const SortTuple *b, { Bucket bucket1; Bucket bucket2; + uint32 hash1; + uint32 hash2; IndexTuple tuple1; IndexTuple tuple2; TuplesortPublic *base = TuplesortstateGetPublic(state); @@ -1409,6 +1411,18 @@ comparetup_index_hash(const SortTuple *a, const SortTuple *b, else if (bucket1 < bucket2) return -1; + /* + * If bucket values are equal, sort by hash values. This allows us to + * insert directly onto bucket/overflow pages, where the index tuples + * are stored in hash order to allow fast binary search within each page. + */ + hash1 = DatumGetUInt32(a->datum1); + hash2 = DatumGetUInt32(b->datum1); + if (hash1 > hash2) + return 1; + else if (hash1 < hash2) + return -1; + /* * If hash values are equal, we sort on ItemPointer. This does not affect * validity of the finished index, but it may be useful to have index