ThinkGeo.com    |     Blog    |     Wiki    |     Support

Not using SQL Server spatial index

I have some code that is currently using ThinkGeo Map Suite Services Edition to query a SQL Server 2008 database for the shape(s) that contain a point.  That code is currently using Map Suite 6, but I am attempting to switch over to using Map Suite 9.



Dim sectionFeatures As Collection(Of Feature)

Dim sectionColumns As String() = {“SECTION”, “TOWNSHIP”}

 sectionFeatures = sectionLayer.QueryTools.GetFeaturesContaining(inPoint, sectionColumns)




When I use Map Suite 6, the query that gets thrown at the database is 



exec sp_executesql N’SELECT [SECTION],[TOWNSHIP],[Shape].STAsBinary() as [Shape],[SECTION_ID] FROM SECTION with(index(S868_idx)) WHERE (geography::STGeomFromText(@geography,4269).STIntersects(Shape)=1);’,N’@Geography varchar(170)’,@Geography=‘POLYGON((-110.7703329915 47.737164355451,-110.7703329915 47.737154355451,-110.7703229915 47.737154355451,-110.7703229915 47.737164355451,-110.7703329915 47.737164355451))’ 



When I use Map Suite 9 (yesterday’s daily build) the query instead is

exec sp_executesql N’SELECT [SECTION],[TOWNSHIP],[Shape].STAsBinary() as [Shape],[SECTION_ID] FROM SECTION WHERE (geometry::STGeomFromText(@Geography,4269).STWithin(geometry::STGeomFromWKB(Shape.STAsBinary(),4269))=1);’,N’@Geography varchar(38)’,@Geography='POINT(-110.7703279915 47.737159355451)'


The top (Map Suite 6) version is supplying the spatial index hint whereas the bottom (Map Suite 9) version is not.  The top query completes in less than a second, the bottom one times out after the default 30 second timeout.  My question is what do I need to do to get Map Suite 9 to generate SQL that takes advantage of the spatial index of the table?  I can see by inspecting the properties of the layer in Visual Studio that the layer knows the name of the spatial index, but it isn’t currently using that index name in the query sent to the database and for some reason the database doesn’t appear to be smart enough to use the index unless it’s told to do so by the query.



Any advice would be appreciated.

Thanks,

John

Hi John,



Please try setting the sectionFeatures.SpatialIndexName = “S868_idx”.



Usually, we don’t need to set the SpatialIndexName property, the MsSql2008FeatureLayer will set it automatically as the first spatial index if exists. If there are more than one indices here and we need to set the property as the index we want to use.



Hope it’s helped.



Any questions please let me know.



Regards,

Peter

I've tried setting the SpatialIndexName as you suggest, but doing so did nothing to alter the query being sent to the database.  As I mentioned in my original post, by inspecting the properties of the layer while running the app in Visual Studio, I could see that it already identified the first spatial index and was already setting it correctly; the spatial index hint just isn't making it into the SQL that is thrown at the database.


I think there is a further problem than just the failure to include the index hint.  If I take the statement being sent to the database, modify it to add the spatial index hint (as immediately below), 



exec sp_executesql N'SELECT [SECTION],[TOWNSHIP],[Shape].STAsBinary() as [Shape],[SECTION_ID] FROM nationaldb.sde.SECTION with(index(S868_idx)) WHERE (geometry::STGeomFromText(@Geography,4269).STWithin(geometry::STGeomFromWKB(Shape.STAsBinary(),4269))=1);',N'@Geography varchar(38)',@Geography='POINT(-110.7703279915 47.737159355451)'



and manually execute it in SQL Server Management Studio, then I get the error "The query processor could not produce a query plan for a query with a spatial index hint. Reason: Could not find required binary spatial method in a condition. Try removing the index hints or removing SET FORCEPLAN.".



My guess (and only a guess at this point) is that the "STWithin(geometry::STGeomFromWKB(Shape.STAsBinary(),4269))" portion of this, which, unless I'm misunderstanding this, is turning every shape in the table one-record-at-a-time into it's WKB representation and then from WKB into a Geometry object so that it can then test for whether a point is within it, prevents SQL Server from being able to use a spatial query hint (or the query optimizer from being able to use a spatial index for that matter) even if it is included.



Hi John,



We did some changes from 6.0 to 9.0. In MsSql Server 2008 only intersects, disjoint, topologicalequal are available for geography.  The code 


Dim sectionFeatures As Collection(Of Feature)
Dim sectionColumns As String() = {“SECTION”, “TOWNSHIP”}
sectionFeatures = sectionLayer.QueryTools.GetFeaturesContaining(inPoint, sectionColumns)

will generate the different SQL statement between 6.0 and 9.0 as you attached before. In 6.0 the logical operation is STIntersects but it’s SWithin in 9.0. Please call the sectionLayer.QueryTools.GetFeaturesIntersecting(inPoint, sectionColumns) method in 9.0 to get the same result as call the sectionLayer.QueryTools.GetFeaturesContaining(inPoint, sectionColumns) method in 6.0.



Thanks,

Peter




Thanks!  That appears to work perfectly for me. 
  
 Thanks, 
 John

Hi John, 
  
 Very glad to hear it worked. 
  
 Thanks, 
 Peter