Skip to content

Commit 043d528

Browse files
authored
Merge pull request #3510 from lonvia/indexing-precompute-count
Indexing: precompute counts of affected rows
2 parents bd0316b + 3905dd6 commit 043d528

File tree

1 file changed

+54
-9
lines changed

1 file changed

+54
-9
lines changed

src/nominatim_db/indexer/indexer.py

+54-9
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"""
88
Main work horse for indexing (computing addresses) the database.
99
"""
10-
from typing import cast, List, Any
10+
from typing import cast, List, Any, Optional
1111
import logging
1212
import time
1313

@@ -83,9 +83,30 @@ async def index_boundaries(self, minrank: int, maxrank: int) -> int:
8383
LOG.warning("Starting indexing boundaries using %s threads",
8484
self.num_threads)
8585

86+
minrank = max(minrank, 4)
87+
maxrank = min(maxrank, 25)
88+
89+
# Precompute number of rows to process for all rows
90+
with connect(self.dsn) as conn:
91+
hstore_info = psycopg.types.TypeInfo.fetch(conn, "hstore")
92+
if hstore_info is None:
93+
raise RuntimeError('Hstore extension is requested but not installed.')
94+
psycopg.types.hstore.register_hstore(hstore_info)
95+
96+
with conn.cursor() as cur:
97+
cur = conn.execute(""" SELECT rank_search, count(*)
98+
FROM placex
99+
WHERE rank_search between %s and %s
100+
AND class = 'boundary' and type = 'administrative'
101+
AND indexed_status > 0
102+
GROUP BY rank_search""",
103+
(minrank, maxrank))
104+
total_tuples = {row.rank_search: row.count for row in cur}
105+
86106
with self.tokenizer.name_analyzer() as analyzer:
87-
for rank in range(max(minrank, 4), min(maxrank, 26)):
88-
total += await self._index(runners.BoundaryRunner(rank, analyzer))
107+
for rank in range(minrank, maxrank + 1):
108+
total += await self._index(runners.BoundaryRunner(rank, analyzer),
109+
total_tuples=total_tuples.get(rank, 0))
89110

90111
return total
91112

@@ -101,6 +122,23 @@ async def index_by_rank(self, minrank: int, maxrank: int) -> int:
101122
LOG.warning("Starting indexing rank (%i to %i) using %i threads",
102123
minrank, maxrank, self.num_threads)
103124

125+
# Precompute number of rows to process for all rows
126+
with connect(self.dsn) as conn:
127+
hstore_info = psycopg.types.TypeInfo.fetch(conn, "hstore")
128+
if hstore_info is None:
129+
raise RuntimeError('Hstore extension is requested but not installed.')
130+
psycopg.types.hstore.register_hstore(hstore_info)
131+
132+
with conn.cursor() as cur:
133+
cur = conn.execute(""" SELECT rank_address, count(*)
134+
FROM placex
135+
WHERE rank_address between %s and %s
136+
AND indexed_status > 0
137+
GROUP BY rank_address""",
138+
(minrank, maxrank))
139+
total_tuples = {row.rank_address: row.count for row in cur}
140+
141+
104142
with self.tokenizer.name_analyzer() as analyzer:
105143
for rank in range(max(1, minrank), maxrank + 1):
106144
if rank >= 30:
@@ -109,11 +147,12 @@ async def index_by_rank(self, minrank: int, maxrank: int) -> int:
109147
batch = 5
110148
else:
111149
batch = 1
112-
total += await self._index(runners.RankRunner(rank, analyzer), batch)
150+
total += await self._index(runners.RankRunner(rank, analyzer),
151+
batch=batch, total_tuples=total_tuples.get(rank, 0))
113152

114153
if maxrank == 30:
115154
total += await self._index(runners.RankRunner(0, analyzer))
116-
total += await self._index(runners.InterpolationRunner(analyzer), 20)
155+
total += await self._index(runners.InterpolationRunner(analyzer), batch=20)
117156

118157
return total
119158

@@ -123,7 +162,7 @@ async def index_postcodes(self) -> int:
123162
"""
124163
LOG.warning("Starting indexing postcodes using %s threads", self.num_threads)
125164

126-
return await self._index(runners.PostcodeRunner(), 20)
165+
return await self._index(runners.PostcodeRunner(), batch=20)
127166

128167

129168
def update_status_table(self) -> None:
@@ -135,14 +174,20 @@ def update_status_table(self) -> None:
135174

136175
conn.commit()
137176

138-
async def _index(self, runner: runners.Runner, batch: int = 1) -> int:
177+
async def _index(self, runner: runners.Runner, batch: int = 1,
178+
total_tuples: Optional[int] = None) -> int:
139179
""" Index a single rank or table. `runner` describes the SQL to use
140180
for indexing. `batch` describes the number of objects that
141-
should be processed with a single SQL statement
181+
should be processed with a single SQL statement.
182+
183+
`total_tuples` may contain the total number of rows to process.
184+
When not supplied, the value will be computed using the
185+
approriate runner function.
142186
"""
143187
LOG.warning("Starting %s (using batch size %s)", runner.name(), batch)
144188

145-
total_tuples = self._prepare_indexing(runner)
189+
if total_tuples is None:
190+
total_tuples = self._prepare_indexing(runner)
146191

147192
progress = ProgressLogger(runner.name(), total_tuples)
148193

0 commit comments

Comments
 (0)