hash_sort_by_hash.v2.patch
application/octet-stream
Filename: hash_sort_by_hash.v2.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
Series: patch v2
| File | + | − |
|---|---|---|
| src/backend/access/hash/hashsort.c | 4 | 3 |
| src/backend/utils/sort/tuplesort.c | 14 | 0 |
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/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index e8da988a73..3a828676d0 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -4461,6 +4461,8 @@ comparetup_index_hash(const SortTuple *a, const SortTuple *b,
{
Bucket bucket1;
Bucket bucket2;
+ uint32 hash1;
+ uint32 hash2;
IndexTuple tuple1;
IndexTuple tuple2;
@@ -4481,6 +4483,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