|
27 | 27 | CREATE, MODIFY, DELETE = 0, 1, 2 |
28 | 28 | DUCKDB_MEMORY_LIMIT = "48GB" |
29 | 29 | DUCKDB_THREADS = 32 |
| 30 | +DUCKDB_MAX_TEMP = "680GB" |
30 | 31 | TAG_SHARDS = 64 |
31 | 32 |
|
32 | 33 | # Replicates osmium.geom.haversine_distance (R = 6372797.560856 m, per libosmium haversine.hpp) so join |
@@ -223,31 +224,23 @@ def stream_changesets(dump: str, start: dt.datetime, end: dt.datetime, work: pat |
223 | 224 | def _build_way_len(con: duckdb.DuckDBPyConnection, work: pathlib.Path) -> None: |
224 | 225 | """way_len(way_id, length): haversine over each open-way-create's node coords (node first-version). |
225 | 226 | A way is dropped (no length) if any node lacks coords or the total exceeds MAX_WAY_LENGTH_M, matching |
226 | | - osmium's InvalidLocationError / guard behaviour.""" |
| 227 | + osmium's InvalidLocationError / guard behaviour. Each node's v1 coord is a single row, so refs join |
| 228 | + straight to raw_nodes with no dedup; validity and length fold into one per-way aggregate.""" |
227 | 229 | nodes = (work / "raw_nodes_*.parquet").as_posix() |
228 | 230 | waynodes = (work / "raw_waynodes_*.parquet").as_posix() |
229 | 231 | con.execute(HAVERSINE_MACRO) |
230 | 232 | con.execute( |
231 | 233 | f"""CREATE TABLE way_len AS |
232 | | - WITH node_loc AS ( |
233 | | - SELECT node_id, any_value(lon) AS lon, any_value(lat) AS lat |
234 | | - FROM read_parquet('{nodes}') GROUP BY node_id |
235 | | - ), |
236 | | - pts AS ( |
237 | | - SELECT wn.way_id, wn.seq, nl.lon, nl.lat |
238 | | - FROM read_parquet('{waynodes}') wn LEFT JOIN node_loc nl USING (node_id) |
239 | | - ), |
240 | | - valid AS ( |
241 | | - SELECT way_id FROM pts GROUP BY way_id HAVING count(*) >= 2 AND count(*) = count(lon) |
| 234 | + WITH pts AS ( |
| 235 | + SELECT wn.way_id, wn.seq, n.lat, n.lon |
| 236 | + FROM read_parquet('{waynodes}') wn LEFT JOIN read_parquet('{nodes}') n USING (node_id) |
242 | 237 | ), |
243 | 238 | seg AS ( |
244 | | - SELECT p.way_id, |
245 | | - hav(p.lat, p.lon, lag(p.lat) OVER w, lag(p.lon) OVER w) AS d |
246 | | - FROM pts p SEMI JOIN valid v ON p.way_id = v.way_id |
247 | | - WINDOW w AS (PARTITION BY p.way_id ORDER BY p.seq) |
| 239 | + SELECT way_id, lat, hav(lat, lon, lag(lat) OVER w, lag(lon) OVER w) AS d |
| 240 | + FROM pts WINDOW w AS (PARTITION BY way_id ORDER BY seq) |
248 | 241 | ) |
249 | 242 | SELECT way_id, sum(d) AS length FROM seg GROUP BY way_id |
250 | | - HAVING sum(d) <= {MAX_WAY_LENGTH_M}""" |
| 243 | + HAVING count(*) >= 2 AND count(*) = count(lat) AND sum(d) <= {MAX_WAY_LENGTH_M}""" |
251 | 244 | ) |
252 | 245 |
|
253 | 246 |
|
@@ -366,6 +359,7 @@ def aggregate(work: pathlib.Path, out: pathlib.Path) -> pathlib.Path: |
366 | 359 | tmp.mkdir(exist_ok=True) |
367 | 360 | con.execute(f"SET temp_directory='{tmp.as_posix()}'") |
368 | 361 | con.execute(f"SET memory_limit='{DUCKDB_MEMORY_LIMIT}'") |
| 362 | + con.execute(f"SET max_temp_directory_size='{DUCKDB_MAX_TEMP}'") |
369 | 363 | con.execute(f"SET threads={DUCKDB_THREADS}") |
370 | 364 | con.execute("SET preserve_insertion_order=false") |
371 | 365 | create_tables(con) |
|
0 commit comments