Skip to content

Commit 27cfb5e

Browse files
authored
Merge pull request #2059 from joto/find-changed-ways
Use roundabout way to find changed ways
2 parents 46bb159 + 556c8e8 commit 27cfb5e

File tree

1 file changed

+45
-24
lines changed

1 file changed

+45
-24
lines changed

src/middle-pgsql.cpp

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ static void load_id_list(pg_conn_t const &db_connection,
7373
std::string const &table,
7474
osmium::index::IdSetSmall<osmid_t> *ids)
7575
{
76-
auto const res =
77-
db_connection.exec(fmt::format("SELECT id FROM {} ORDER BY id", table));
76+
auto const res = db_connection.exec(
77+
fmt::format("SELECT DISTINCT id FROM {} ORDER BY id", table));
7878
for (int n = 0; n < res.num_tuples(); ++n) {
7979
ids->set(osmium::string_to_object_id(res.get_value(n, 0)));
8080
}
@@ -822,48 +822,69 @@ void middle_pgsql_t::get_node_parents(
822822

823823
send_id_list(m_db_connection, "osm2pgsql_changed_nodes", changed_nodes);
824824

825-
m_db_connection.exec("ANALYZE osm2pgsql_changed_nodes");
825+
std::vector<std::string> queries;
826+
827+
queries.emplace_back("ANALYZE osm2pgsql_changed_nodes");
826828

827829
bool const has_bucket_index =
828830
check_bucket_index(&m_db_connection, m_options->prefix);
829831

830832
if (has_bucket_index) {
831-
m_db_connection.exec(build_sql(*m_options, R"(
832-
WITH changed_buckets AS (
833-
SELECT array_agg(id) AS node_ids, id >> {way_node_index_id_shift} AS bucket
834-
FROM osm2pgsql_changed_nodes GROUP BY id >> {way_node_index_id_shift}
835-
)
836-
INSERT INTO osm2pgsql_changed_ways
837-
SELECT DISTINCT w.id
838-
FROM {schema}"{prefix}_ways" w, changed_buckets b
839-
WHERE w.nodes && b.node_ids
840-
AND {schema}"{prefix}_index_bucket"(w.nodes)
841-
&& ARRAY[b.bucket];
842-
)"));
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.
839+
queries.emplace_back(R"(
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()");
843860
} else {
844-
m_db_connection.exec(build_sql(*m_options, R"(
861+
queries.emplace_back(R"(
845862
INSERT INTO osm2pgsql_changed_ways
846-
SELECT DISTINCT w.id
863+
SELECT w.id
847864
FROM {schema}"{prefix}_ways" w, osm2pgsql_changed_nodes n
848865
WHERE w.nodes && ARRAY[n.id]
849-
)"));
866+
)");
850867
}
851868

852869
if (m_options->middle_database_format == 1) {
853-
m_db_connection.exec(build_sql(*m_options, R"(
870+
queries.emplace_back(R"(
854871
INSERT INTO osm2pgsql_changed_relations
855-
SELECT DISTINCT r.id
872+
SELECT r.id
856873
FROM {schema}"{prefix}_rels" r, osm2pgsql_changed_nodes n
857874
WHERE r.parts && ARRAY[n.id]
858875
AND r.parts[1:way_off] && ARRAY[n.id]
859-
)"));
876+
)");
860877
} else {
861-
m_db_connection.exec(build_sql(*m_options, R"(
878+
queries.emplace_back(R"(
862879
INSERT INTO osm2pgsql_changed_relations
863-
SELECT DISTINCT r.id
880+
SELECT r.id
864881
FROM {schema}"{prefix}_rels" r, osm2pgsql_changed_nodes c
865882
WHERE {schema}"{prefix}_member_ids"(r.members, 'N'::char) && ARRAY[c.id];
866-
)"));
883+
)");
884+
}
885+
886+
for (auto const &query : queries) {
887+
m_db_connection.exec(build_sql(*m_options, query));
867888
}
868889

869890
load_id_list(m_db_connection, "osm2pgsql_changed_ways", parent_ways);

0 commit comments

Comments
 (0)