mirror of
https://github.com/osm-search/Nominatim.git
synced 2024-11-22 21:28:10 +03:00
use constant expressions to select partial indexes in reverse
When expressions are generated with SQLAlchemy, any constants are replaced with bind parameters. The bind parameters become parameters of prepared statements. The result is that the query planner tends to oversee that the partial indexes can be used.
This commit is contained in:
parent
3e2dd59a94
commit
75139961a3
@ -17,6 +17,7 @@ import nominatim.api.results as nres
|
|||||||
from nominatim.api.logging import log
|
from nominatim.api.logging import log
|
||||||
from nominatim.api.types import AnyPoint, DataLayer, ReverseDetails, GeometryFormat, Bbox
|
from nominatim.api.types import AnyPoint, DataLayer, ReverseDetails, GeometryFormat, Bbox
|
||||||
from nominatim.db.sqlalchemy_types import Geometry
|
from nominatim.db.sqlalchemy_types import Geometry
|
||||||
|
import nominatim.db.sqlalchemy_functions as snfn
|
||||||
|
|
||||||
# In SQLAlchemy expression which compare with NULL need to be expressed with
|
# In SQLAlchemy expression which compare with NULL need to be expressed with
|
||||||
# the equal sign.
|
# the equal sign.
|
||||||
@ -348,13 +349,8 @@ class ReverseGeocoder:
|
|||||||
# later only a minimum of results needs to be checked with ST_Contains.
|
# later only a minimum of results needs to be checked with ST_Contains.
|
||||||
inner = sa.select(t, sa.literal(0.0).label('distance'))\
|
inner = sa.select(t, sa.literal(0.0).label('distance'))\
|
||||||
.where(t.c.rank_search.between(5, MAX_RANK_PARAM))\
|
.where(t.c.rank_search.between(5, MAX_RANK_PARAM))\
|
||||||
.where(t.c.rank_address.between(5, 25))\
|
|
||||||
.where(t.c.geometry.is_area())\
|
|
||||||
.where(t.c.geometry.intersects(WKT_PARAM))\
|
.where(t.c.geometry.intersects(WKT_PARAM))\
|
||||||
.where(t.c.name != None)\
|
.where(snfn.select_index_placex_geometry_reverse_lookuppolygon('placex'))\
|
||||||
.where(t.c.indexed_status == 0)\
|
|
||||||
.where(t.c.linked_place_id == None)\
|
|
||||||
.where(t.c.type != 'postcode')\
|
|
||||||
.order_by(sa.desc(t.c.rank_search))\
|
.order_by(sa.desc(t.c.rank_search))\
|
||||||
.limit(50)\
|
.limit(50)\
|
||||||
.subquery('area')
|
.subquery('area')
|
||||||
@ -373,14 +369,10 @@ class ReverseGeocoder:
|
|||||||
log().comment('Search for better matching place nodes inside the area')
|
log().comment('Search for better matching place nodes inside the area')
|
||||||
inner = sa.select(t,
|
inner = sa.select(t,
|
||||||
t.c.geometry.ST_Distance(WKT_PARAM).label('distance'))\
|
t.c.geometry.ST_Distance(WKT_PARAM).label('distance'))\
|
||||||
.where(t.c.osm_type == 'N')\
|
|
||||||
.where(t.c.rank_search > address_row.rank_search)\
|
.where(t.c.rank_search > address_row.rank_search)\
|
||||||
.where(t.c.rank_search <= MAX_RANK_PARAM)\
|
.where(t.c.rank_search <= MAX_RANK_PARAM)\
|
||||||
.where(t.c.rank_address.between(5, 25))\
|
|
||||||
.where(t.c.name != None)\
|
|
||||||
.where(t.c.indexed_status == 0)\
|
.where(t.c.indexed_status == 0)\
|
||||||
.where(t.c.linked_place_id == None)\
|
.where(snfn.select_index_placex_geometry_reverse_lookupplacenode('placex'))\
|
||||||
.where(t.c.type != 'postcode')\
|
|
||||||
.where(t.c.geometry
|
.where(t.c.geometry
|
||||||
.ST_Buffer(sa.func.reverse_place_diameter(t.c.rank_search))
|
.ST_Buffer(sa.func.reverse_place_diameter(t.c.rank_search))
|
||||||
.intersects(WKT_PARAM))\
|
.intersects(WKT_PARAM))\
|
||||||
@ -476,15 +468,11 @@ class ReverseGeocoder:
|
|||||||
|
|
||||||
inner = sa.select(t,
|
inner = sa.select(t,
|
||||||
t.c.geometry.ST_Distance(WKT_PARAM).label('distance'))\
|
t.c.geometry.ST_Distance(WKT_PARAM).label('distance'))\
|
||||||
.where(t.c.osm_type == 'N')\
|
|
||||||
.where(t.c.rank_search > 4)\
|
.where(t.c.rank_search > 4)\
|
||||||
.where(t.c.rank_search <= MAX_RANK_PARAM)\
|
.where(t.c.rank_search <= MAX_RANK_PARAM)\
|
||||||
.where(t.c.rank_address.between(5, 25))\
|
|
||||||
.where(t.c.name != None)\
|
|
||||||
.where(t.c.indexed_status == 0)\
|
.where(t.c.indexed_status == 0)\
|
||||||
.where(t.c.linked_place_id == None)\
|
|
||||||
.where(t.c.type != 'postcode')\
|
|
||||||
.where(t.c.country_code.in_(ccodes))\
|
.where(t.c.country_code.in_(ccodes))\
|
||||||
|
.where(snfn.select_index_placex_geometry_reverse_lookupplacenode('placex'))\
|
||||||
.where(t.c.geometry
|
.where(t.c.geometry
|
||||||
.ST_Buffer(sa.func.reverse_place_diameter(t.c.rank_search))
|
.ST_Buffer(sa.func.reverse_place_diameter(t.c.rank_search))
|
||||||
.intersects(WKT_PARAM))\
|
.intersects(WKT_PARAM))\
|
||||||
|
34
nominatim/db/sqlalchemy_functions.py
Normal file
34
nominatim/db/sqlalchemy_functions.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# This file is part of Nominatim. (https://nominatim.org)
|
||||||
|
#
|
||||||
|
# Copyright (C) 2023 by the Nominatim developer community.
|
||||||
|
# For a full list of authors see the git log.
|
||||||
|
"""
|
||||||
|
Custom functions and expressions for SQLAlchemy.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
def select_index_placex_geometry_reverse_lookuppolygon(table: str) -> 'sa.TextClause':
|
||||||
|
""" Create an expression with the necessary conditions over a placex
|
||||||
|
table that the index 'idx_placex_geometry_reverse_lookupPolygon'
|
||||||
|
can be used.
|
||||||
|
"""
|
||||||
|
return sa.text(f"ST_GeometryType({table}.geometry) in ('ST_Polygon', 'ST_MultiPolygon')"
|
||||||
|
f" AND {table}.rank_address between 4 and 25"
|
||||||
|
f" AND {table}.type != 'postcode'"
|
||||||
|
f" AND {table}.name is not null"
|
||||||
|
f" AND {table}.indexed_status = 0"
|
||||||
|
f" AND {table}.linked_place_id is null")
|
||||||
|
|
||||||
|
def select_index_placex_geometry_reverse_lookupplacenode(table: str) -> 'sa.TextClause':
|
||||||
|
""" Create an expression with the necessary conditions over a placex
|
||||||
|
table that the index 'idx_placex_geometry_reverse_lookupPlaceNode'
|
||||||
|
can be used.
|
||||||
|
"""
|
||||||
|
return sa.text(f"{table}.rank_address between 4 and 25"
|
||||||
|
f" AND {table}.type != 'postcode'"
|
||||||
|
f" AND {table}.name is not null"
|
||||||
|
f" AND {table}.linked_place_id is null"
|
||||||
|
f" AND {table}.osm_type = 'N'")
|
Loading…
Reference in New Issue
Block a user