Skip to content

Commit 556c8e8

Browse files
committed
Put query for finding parent ways from nodes inside a PL/pgSQL function
The query we had before would sometimes result in really bad performance when the query planner in PostgreQL decides that it needs to use sequential scans on the ways table. This is due to the statistics being way off. By running the query for each node ids on its own we hopefully trick the query planner into always using an index lookup. See #2056
1 parent 29ff7ee commit 556c8e8

File tree

1 file changed

+26
-11
lines changed

1 file changed

+26
-11
lines changed

src/middle-pgsql.cpp

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -830,18 +830,33 @@ void middle_pgsql_t::get_node_parents(
830830
check_bucket_index(&m_db_connection, m_options->prefix);
831831

832832
if (has_bucket_index) {
833+
// The query to get the parent ways of changed nodes is "hidden"
834+
// inside a PL/pgSQL function so that the query planner only sees
835+
// a single node id that is being queried for. If we ask for all
836+
// nodes at the same time the query planner sometimes thinks it is
837+
// better to do a full table scan which totally destroys performance.
838+
// This is due to the PostgreSQL statistics on ARRAYs being way off.
833839
queries.emplace_back(R"(
834-
WITH changed_buckets AS (
835-
SELECT array_agg(id) AS node_ids, id >> {way_node_index_id_shift} AS bucket
836-
FROM osm2pgsql_changed_nodes GROUP BY id >> {way_node_index_id_shift}
837-
)
838-
INSERT INTO osm2pgsql_changed_ways
839-
SELECT w.id
840-
FROM {schema}"{prefix}_ways" w, changed_buckets b
841-
WHERE w.nodes && b.node_ids
842-
AND {schema}"{prefix}_index_bucket"(w.nodes)
843-
&& ARRAY[b.bucket];
844-
)");
840+
CREATE OR REPLACE FUNCTION osm2pgsql_find_changed_ways() RETURNS void AS $$
841+
DECLARE
842+
changed_buckets RECORD;
843+
BEGIN
844+
FOR changed_buckets IN
845+
SELECT array_agg(id) AS node_ids, id >> {way_node_index_id_shift} AS bucket
846+
FROM osm2pgsql_changed_nodes GROUP BY id >> {way_node_index_id_shift}
847+
LOOP
848+
INSERT INTO osm2pgsql_changed_ways
849+
SELECT DISTINCT w.id
850+
FROM {schema}"{prefix}_ways" w
851+
WHERE w.nodes && changed_buckets.node_ids
852+
AND {schema}"{prefix}_index_bucket"(w.nodes)
853+
&& ARRAY[changed_buckets.bucket];
854+
END LOOP;
855+
END;
856+
$$ LANGUAGE plpgsql
857+
)");
858+
queries.emplace_back("SELECT osm2pgsql_find_changed_ways()");
859+
queries.emplace_back("DROP FUNCTION osm2pgsql_find_changed_ways()");
845860
} else {
846861
queries.emplace_back(R"(
847862
INSERT INTO osm2pgsql_changed_ways

0 commit comments

Comments
 (0)