v10-0001-Add-sort-support-for-point-gist_point_sortsuppor.patch
application/octet-stream
Filename: v10-0001-Add-sort-support-for-point-gist_point_sortsuppor.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch v10-0001
Subject: Add sort support for point gist_point_sortsupport
| File | + | − |
|---|---|---|
| src/backend/access/gist/gistproc.c | 86 | 0 |
| src/include/catalog/pg_proc.dat | 3 | 0 |
From fa850a5ebbb78cad1e57128a331e780379a44f41 Mon Sep 17 00:00:00 2001
From: Andrey <amborodin@acm.org>
Date: Sun, 25 Aug 2019 12:42:36 +0500
Subject: [PATCH v10 1/2] Add sort support for point gist_point_sortsupport
---
src/backend/access/gist/gistproc.c | 86 ++++++++++++++++++++++++++++++
src/include/catalog/pg_proc.dat | 3 ++
2 files changed, 89 insertions(+)
diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c
index 9ace64c3c4..f7fb60910d 100644
--- a/src/backend/access/gist/gistproc.c
+++ b/src/backend/access/gist/gistproc.c
@@ -24,12 +24,18 @@
#include "utils/builtins.h"
#include "utils/float.h"
#include "utils/geo_decls.h"
+#include "utils/sortsupport.h"
static bool gist_box_leaf_consistent(BOX *key, BOX *query,
StrategyNumber strategy);
static bool rtree_internal_consistent(BOX *key, BOX *query,
StrategyNumber strategy);
+static int64 part_bits32_by2(uint32 x);
+static int64 interleave_bits32(uint32 x, uint32 y);
+static inline uint64 point_zorder_internal(Point *p);
+static int gist_bbox_fastcmp(Datum x, Datum y, SortSupport ssup);
+
/* Minimum accepted ratio of split */
#define LIMIT_RATIO 0.3
@@ -1540,3 +1546,83 @@ gist_poly_distance(PG_FUNCTION_ARGS)
PG_RETURN_FLOAT8(distance);
}
+
+/* Z-order routines */
+/* Interleave 32 bits with zeroes */
+static int64
+part_bits32_by2(uint32 x)
+{
+ uint64 n = x;
+
+ n = (n | (n << 16)) & UINT64CONST(0x0000FFFF0000FFFF);
+ n = (n | (n << 8)) & UINT64CONST(0x00FF00FF00FF00FF);
+ n = (n | (n << 4)) & UINT64CONST(0x0F0F0F0F0F0F0F0F);
+ n = (n | (n << 2)) & UINT64CONST(0x3333333333333333);
+ n = (n | (n << 1)) & UINT64CONST(0x5555555555555555);
+
+ return n;
+}
+
+/*
+ * Compute Z-order for integers. Also called Morton code.
+ */
+static int64
+interleave_bits32(uint32 x, uint32 y)
+{
+ return part_bits32_by2(x) | (part_bits32_by2(y) << 1);
+}
+
+/* Compute Z-order for Point */
+static inline uint64
+point_zorder_internal(Point *p)
+{
+ /*
+ * In this function we need to compute Morton codes for non-integral
+ * components p->x and p->y. But Morton codes are defined only for
+ * integral values.
+ * We expect floats to be in IEEE format, and the sort order of IEEE
+ * floats is mostly correlated to the binary sort order of the bits
+ * reinterpreted as an int. It isn't in some special cases, but for this
+ * use case we don't really care about that, we're just trying to
+ * encourage locality.
+ * There is a big jump in integer value (whether signed or
+ * unsigned) as you cross from positive to negative floats, and then the
+ * sort order is reversed. This can have negative effect on searches when
+ * query window touches many quadrants simulatously. In worst case this
+ * seaches can be x4 more costly.
+ * We generate a Morton code that interleaves the bits of N integers
+ * to produce a single integer that preserves locality: things that were
+ * close in the N dimensional space are close in the resulting integer.
+ */
+ union {
+ float f;
+ uint32 i;
+ } a,b;
+ a.f = p->x;
+ b.f = p->y;
+ if (isnan(a.f))
+ a.i = PG_INT32_MAX;
+ if (isnan(b.f))
+ b.i = PG_INT32_MAX;
+ return interleave_bits32(a.i, b.i);
+}
+
+static int
+gist_bbox_fastcmp(Datum x, Datum y, SortSupport ssup)
+{
+ Point *p1 = &(DatumGetBoxP(x)->low);
+ Point *p2 = &(DatumGetBoxP(y)->low);
+ uint64 z1 = point_zorder_internal(p1);
+ uint64 z2 = point_zorder_internal(p2);
+
+ return z1 == z2 ? 0 : z1 > z2 ? 1 : -1;
+}
+
+Datum
+gist_point_sortsupport(PG_FUNCTION_ARGS)
+{
+ SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
+
+ ssup->comparator = gist_bbox_fastcmp;
+ PG_RETURN_VOID();
+}
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 082a11f270..7e09e022f7 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8044,6 +8044,9 @@
proname => 'gist_poly_distance', prorettype => 'float8',
proargtypes => 'internal polygon int2 oid internal',
prosrc => 'gist_poly_distance' },
+{ oid => '3435', descr => 'sort support',
+ proname => 'gist_point_sortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'gist_point_sortsupport' },
# GIN array support
{ oid => '2743', descr => 'GIN array support',
--
2.24.3 (Apple Git-128)