I did some experiments over the last month with different kinds of queries 
joining "nodes" with "ways" in various way in the database. Either through ids 
using a "nodes" array, special join tables connecting node_ids with way_ids or 
using the spatial indexes. This in various combinations of using the middle 
tables or creating special tables for this use case and so on. All the options 
were quite slow. Interestingly enough, the spatial queries worked somewhat 
better than going through ids.

So I believe we currently have no good way of handling this use case, at least 
for databases that are updated often. Running joins like this on a database 
that needs half a day to import and then lives for a long time isn't a huge 
problem, because it doesn't add that much extra processing time, but if we want 
minutely updates, the current situation is clearly not great.

So I thought about what kind of functionality we could add to osm2pgsql to help 
with this use case. Here is the idea:
* Add an optional in-memory "id cache" to node tables. This keeps track of all 
nodes added to a table in the `process_node()` function.
* In the `process_way()` function you can check this cache quickly and do extra 
processing based on this information.
* In append mode the cache is initialized after nodes are imported with the 
content of the database table.

Here is an example to make this clearer:
* You have all node barriers like gates etc. stored in a "barriers" table with 
the id cache.
* When processing ways that have a "highway" tag, you check all member nodes of 
the highway whether they are in the cache, if yes, it means you have a barrier 
on the road and you add them to a special "barriers_in_highways" table which 
includes at least the node_id and the way_id, but can include more information 
such as the geometry of the node and/or way, highway type, etc. You can not add 
the "barrier" type at this point because you don't have that information.
* After osm2pgsql runs you can use osm2pgsql-gen (or just run an sql script) to 
add extra information to the "barriers_in_highways" table. For instance to add 
the barrier type you just need a field that's NULL and that you fill with the 
corresponding information from the "barriers" table. Once it is set, it isn't 
NULL any more, so you don't have to do this over and over.

In this example it can happen that a barrier node is in more than one highway 
way. At render time you can choose, for instance, only to render the barrier on 
the highest road class or something like that. That kind of processing is 
cheap, because there is no join involved any more and you only have very few 
entries in your bounding box in the barriers_on_highways table.

I have some proof-of-concept code that makes all of this happen and it looks 
reasonable to me so far. This solution has the advantage that it doesn't add 
much memory overhead (as long as the table cached isn't too large) and is 
reasonably easy to understand (much easier than two-stage processing) and works 
okay with updates. But it will not work with really large lists of nodes, I 
wouldn't want to do this for all addresses or so. We'll have to see in practice 
how far we can stretch this.

Does this sound like a reasonable approach? Can you see any problems with this? 
Does it address the use cases you have?

-- 
Reply to this email directly or view it on GitHub:
https://github.com/osm2pgsql-dev/osm2pgsql/discussions/2455#discussioncomment-16447971
You are receiving this because you are subscribed to this thread.

Message ID: 
<osm2pgsql-dev/osm2pgsql/repo-discussions/2455/comments/[email protected]>
_______________________________________________
Tile-serving mailing list
[email protected]
https://lists.openstreetmap.org/listinfo/tile-serving

Reply via email to