I’m attempting to convert some code I have from using Map Suite Services Edition version 6 to use version 9. I’ve now run into an issue in that drawing a map containing a MsSql2008FeatureLayer is very slow. In Map Suite 6 drawing this map would take at most a couple seconds, but when using Map Suite 9 it is taking over a minute. One of the layers in the map is a SQL Server 2008 database table with approximately 230,000 records (of which only a handful are in view in the current map extent). When I attempt to draw a map that contains that layer, I wait for approximately 30 seconds before pausing the code and I see from the call stack that what Map Suite is doing is calling ThinkGeo.MapSuite.Core.MsSql2008FeatureSource.GetBoundingBoxCore. Using SQL Server Profiler I can see that Map Suite is sending the following SQL to the database
DECLARE @polygon01 geometry;
SELECT TOP 1 @polygon01 = geometry::STGeomFromWKB(Shape.STAsBinary(),4326) FROM TOWNSHIP WHERE Shape IS NOT NULL;
SELECT @polygon01 = @polygon01.STUnion(geometry::STGeomFromWKB(Shape.STAsBinary(),4326).STEnvelope()).STEnvelope() FROM TOWNSHIP
WHERE Shape IS NOT NULL;
SELECT @polygon01.STAsBinary();
If I’m understanding this correctly, what the above SQL is doing is a union of the envelopes of all 230,000 shapes in the database table and returning the resulting envelope. No wonder it takes approximately 62 seconds to complete. I’ve looked at the properties of MsSql2008FeatureLayer but cannot see anything obvious to set to tell it not to compute the bounding box of the layer. HasBoundingBox seems promising in that regard, but as it is a read-only property, isn’t appropriate to set.
Any suggestion on how I can get Map Suite 9 to draw MsSql2008FeatureLayers as quickly as Map Suite 6 did would be greatly appreciated.
Thanks,
John
Drawing a MsSql2008FeatureLayer
Hi John,
Yes you are right, the SQL you appended here is doing a union of the envelopes of all features, and it was executed by the database engine. In Map Suite 9 we did more strict checks for SQL statement than Map Suite 6, this may lose a bit of performance. In Map Suite 9 the BBOX will be cached and refreshed for SpatialDataType.Geography in MsSql2008FeatureSource when the GetBoundingBox() method is called.
There is a workaround for this. As you mentioned that the SQL in 6 is more quickly than 9, we can replace or rebuild the SQL in the ExecutingSqlStatement event.
The following is the code snippets:
void LoadMsSql2008FeatureLayer_ExecutingSqlStatement(object sender, ExecutingSqlStatementMsSql2008FeatureSourceEventArgs e)
{
if (e.ExecutingSqlStatementType == ExecutingSqlStatementType.GetBoundingBox)
{
e.SqlStatement = “”;// your sql statement
}
}
Hope it’s helpful.
Thanks,
Peter
That worked quite well. I created a new class inheriting from MsSql2008FeatureLayer and within that new class added the handler you mention supplying the following SQL
e.SqlStatement = “SELECT geometry::STGeomFromText(‘POLYGON((-180 0, 0 0, 0 90, -180 90, -180 0))’, 4326).STAsBinary();”;
This tells it that the layer covers the entire western half of the northern hemisphere.
It’s definitely a decent workaround to the issue. It would make me feel considerably safer if there was actually a built-in Map Suite class suitable for working with large tables in a SQL Server database however. A class that implements its methods in such a way that there are no reasonable (“reasonable” would obviously not include GetAllFeatures) functions that can be called on it that don’t perform well against a 10 million record table. Better still would be new classes that take advantage of the better spatial support of SQL Server 2012 and 2014 rather than limiting themselves to what was available in SQL Server 2008. Maybe the MsSqlServer2008FeatureLayer already detects the SQL Server version and adjusts the SQL sent to the database accordingly and I’m just not witnessing that due to still being stuck hitting 2008 for a couple more months.
Thank you very much for the workaround.
John
Hi John,
Very glad to hear that it worked for you.
Thanks for your suggestion very much. You are right. The MsSql2008FeatureSource is also suited for 2012 and 2014 commonly. For the specific functions we can create a new class override from MsSql2008FeatureSouce.
Thanks,
Peter