简体   繁体   中英

oracle geocoding query is really slow, how could i optimize a dynamic field?

I have an Oracle table 12K records/gyms, and the query below takes approximately ~0.3s:

SELECT (acos(sin(41.922682*0.017453293) * 
sin(to_number(LATITUDE)*0.017453293) + cos(41.922682*0.017453293) *
cos(to_number(LATITUDE)*0.017453293) * cos(to_number(LONGITUDE)*0.017453293 -
(-87.65432*0.017453293)))*3959) as distance 
FROM gym

However, I would like to return all of the records where distance <= 10, and as soon as I run the following query, my query execution time jumps up to ~5.0s:

SELECT * from (SELECT (acos(sin(41.922682*0.017453293) *
sin(to_number(LATITUDE)*0.017453293) + cos(41.922682*0.017453293) *
cos(to_number(LATITUDE)*0.017453293) * cos(to_number(LONGITUDE)*0.017453293 -
(-87.65432*0.017453293)))*3959) 
as distance FROM gym) 
WHERE distance <= 10 
ORDER BY distance asc

Any idea how I can optimize this in Oracle?

Most important:

  • use a where clause to exclude all longitudes and latitudes that will be more than 10 km/miles (?) away from your point. So you only need to make your calculation for the window within a 10km/miles block.

as an and very rough approximation you could use 0.1 degree as a rule, this is 11km at the equator,and less elsewhere so add

 WHERE (longitude - -87.65)<0.1 and (latitude - 41.922)<0.1

(If you use nested queries, add this to the deepest level)

  • Since your distance is smaller than 10 km or mile, you can consider the length of one unit latitude/longitude as constant, and calculate them once using your formula. Than you can use pythagoras rule to calculate the distance (after adding the bounding box). This is basically why people usually use projected data for calculations.

Other things:

  • order by is always slow if you don't have an index. Do you need to order?
  • save your longitude and latitude as numbers in your table. Why would you store them different in a database?

With money. Specifically, Oracle Spatial.

1) How are you measuring 0.3 seconds for the first query? I'll wager that you are measuring the time required to fetch the first row rather than the time required to fetch the last row. Most client tools will start displaying results long before the database has finished producing them if that is possible (which it almost certainly is if there is no ORDER BY ). So you're probably measuring the time required by the first query to calculate the distance to the first 50 or 500 gyms against the time required by the last query to calculate the distance to all 12,000 gyms.

2) Oracle Locator is a feature that comes with all editions of the Oracle database that includes the ability to use spatial indexes and that provides built-in methods for computing distance. It's not nearly as powerful as Oracle Spatial but it should be more than sufficient for what you're discussing here.

3) If you want to roll your own, I'd second johanvdw's suggestion of using a bounding box .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM