Update: Since writing this post we decided to migrate our geospatial data to an ElasticSearch database, which yielded better results.
I'm new to SQL and I need help to optimize a spatial query so that it runs under in under 2 seconds. We have already tried some suggestions found on various sites (More on that below).
Background
We have a table [Id, Geometry] of about 300,000 geometric shapes of varying sizes and complexity, stored as geometry data types. We have created a spatial index for the Geometry using the code snippet below.
CREATE SPATIAL INDEX [IX_Geometry_Spatial]
ON [dbo].[Geometries] ([Geometry]) USING GEOMETRY_AUTO_GRID
WITH (
BOUNDING_BOX = (XMAX = 24.43359375, XMIN = 10.810546875, YMAX = 69.2249968541159, YMIN = 55.2791152920156)
);
What we want is to find all the geometric shapes that intersects with an input geometric shape. This is done by using the following query.
DECLARE @g geometry;
SET @g = geometry::STGeomFromText('POLYGON ((x0 y0, ...))', 4326); -- A Worst Case Polygon containing 1442 data points
SELECT Count(Id)
FROM Geometries
WHERE Geometries.Geometry.Filter(@g.Reduce(.25)) = 1
For some worst case input geometric shapes (large, complex polygons) this execution takes about 7-10 seconds.
This is the execution plan for the query:
We can see that we hit the spatial index, but the most expensive operation is the clustered index seek (Clustered)
Clustered index seek details:
Spatial index seek details:
Questions
Shouldn't the heavy lifting be done by the spatial index, not the clustered index?
Can the query be improved by changing settings for the spatial index? What settings should we use (for GRIDS, CELLS_PER_OBJECT, etc.)?
How can the execution time be shortened overall, or is 7-10 seconds what you can expect for this kind of query?
What we have tried, that helped
Each of these saved roughly a few seconds.
- Checked for index fragmentation, and rebuilt indexes.
- Switched intersection method from
STIntersect()
toFilter()
- Reduced the input geometry with
Reduce(.25)
. This Reduces the geometry from 1442 data points to 7. (If we decide to use this, it will have to be dynamic for different inputs, but that's another issue.) - Introduced a new table column
SimpleGeometry
which contains the bounding boxes of all the geometry objects from theGeometry
column. Created a newSimpleGeometry
spatial index and usedSimpleGeometry
for the lookup instead ofGeometry
. (Not in use in query example.)