 <?xml-stylesheet type="text/css" href="https://www.esdm.co.uk/Data/style/rss1.css" ?> <?xml-stylesheet type="text/xsl" href="https://www.esdm.co.uk/Data/style/rss1.xsl" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
  <channel>
    <title>The knowledge base blog</title>
    <link>https://www.esdm.co.uk/knowledge</link>
    <description />
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>mojoPortal Blog Module</generator>
    <language>en-GB</language>
    <ttl>120</ttl>
    <atom:link href="https://www.esdm.co.uk/Blog/RSS.aspx?p=138~108~24" rel="self" type="application/rss+xml" />
    <itunes:owner />
    <itunes:explicit>no</itunes:explicit>
    <item>
      <title>Optimising SQL Server spatial indexing - let sql do the work..</title>
      <description><![CDATA[<p>Note – this will take a LONG time to run – quite possibly many hours - on a big dataset as it drops and recreates the index using different parameters – sledgehammer approach, but given the permutations available in SQL server spatial indexing and the level of confusion around optimising – this is the empirical approach.</p>

<p>lifted from here: <a href="http://stackoverflow.com/questions/2920948/selecting-a-good-sql-server-2008-spatial-index-with-large-polygons">http://stackoverflow.com/questions/2920948/selecting-a-good-sql-server-2008-spatial-index-with-large-polygons</a></p>

<p>Basically crate the SPROC listed at the bottom, then setup some example calls (3 or 4 different ones to minimise caching artefacts)</p>

<p>Then set it running and go on holiday …</p>

<h2>Setup your parameters:</h2>

<p>DECLARE @g1 VARCHAR(MAX)<br />
SET @g1 = 'GEOMETRY::STGeomFromText(''POLYGON((252783.989267352 461095.507712082,260134.010732648 461095.507712082,260134.010732648 465068.492287918,252783.989267352 465068.492287918,252783.989267352 461095.507712082))'', 28992)'<br />
DECLARE @g2 VARCHAR(MAX)<br />
SET @g2 = 'GEOMETRY::STGeomFromText(''POLYGON((5580.146375 5340.100667,655613.186375 5340.100667,655613.186375 1219811.501845,5580.146375 1219811.501845,5580.146375 5340.100667))'',28992)'<br />
exec sp_tune_spatial_index 'OBSVEG.OBS_Locations' ,'sidx_OBS_Locations_geom',2,8,@g1,@g2</p>

<h2>Create Stored procedure:</h2>

<p><em>N.B. Assumes geometry field is called geom</em><br />
<em>N.B. You MUST modify the SPROC to use extents for your SRID</em></p>

<pre class="csharpcode">
<span class="kwrd">USE</span> [CMSI-OBSVEG]
<span class="kwrd">GO</span>
/****** <span class="kwrd">Object</span>:  StoredProcedure [dbo].[sp_tune_spatial_index]    Script <span class="kwrd">Date</span>: 10/01/2013 11:35:27 ******/
<span class="kwrd">SET</span> ANSI_NULLS <span class="kwrd">ON</span>
<span class="kwrd">GO</span>
<span class="kwrd">SET</span> QUOTED_IDENTIFIER <span class="kwrd">ON</span>
<span class="kwrd">GO</span>

<span class="kwrd">ALTER</span> <span class="kwrd">PROCEDURE</span> [dbo].[sp_tune_spatial_index]
(
  @tabnm                <span class="kwrd">VARCHAR</span>(<span class="kwrd">MAX</span>),    <span class="rem">-- This parameter stores the name of the spatial table for which you are tuning the index</span>
    @idxnm                <span class="kwrd">VARCHAR</span>(<span class="kwrd">MAX</span>),    <span class="rem">-- This parameter stores the name of the spatial index of the named table</span>
    @min_cells_per_obj    <span class="kwrd">INT</span>,            <span class="rem">-- Minimum Cells Per Object to test on. Suggested to start at 2.</span>
    @max_cells_per_obj    <span class="kwrd">INT</span>,            <span class="rem">-- Maximum Cells Per Object to test on.</span>
    
    /*    The test requires two geometry instances <span class="kwrd">to</span> <span class="kwrd">use</span> <span class="kwrd">in</span> test query 1 <span class="kwrd">and</span> 2.
        The <span class="kwrd">first</span> one should cover the area <span class="kwrd">of</span> <span class="kwrd">default</span> extent. The <span class="kwrd">second</span> should
        cover an area roughly the <span class="kwrd">size</span> <span class="kwrd">of</span> the area shown <span class="kwrd">when</span> zoomed <span class="kwrd">in</span>, panning
        around. It <span class="kwrd">is</span> required that the <span class="kwrd">variable</span> store a string that will <span class="kwrd">create</span>
        the geometry instance since this will be done within the <span class="kwrd">procedure</span> <span class="kwrd">and</span> 
        cannot be a <span class="kwrd">variable</span> <span class="kwrd">of</span> type: GEOMETRY. The SRID <span class="kwrd">of</span> these instances must
        <span class="kwrd">match</span> that <span class="kwrd">of</span> the <span class="kwrd">table</span> you <span class="kwrd">are</span> testing. */
    @testgeom1            <span class="kwrd">VARCHAR</span>(<span class="kwrd">MAX</span>),    <span class="rem">-- This parameter stores the first geometry instance creation string that will be used in the test</span>
    @testgeom2            <span class="kwrd">VARCHAR</span>(<span class="kwrd">MAX</span>)    <span class="rem">-- This parameter stores the second geometry instance creation string that will be used in the test</span>
    
)

<span class="kwrd">AS</span>

<span class="kwrd">SET</span> NOCOUNT <span class="kwrd">ON</span>;

/*    <span class="kwrd">Prior</span> <span class="kwrd">to</span> running this <span class="kwrd">procedure</span>, two tables <span class="kwrd">are</span> required. These tables <span class="kwrd">are</span> 
    created here <span class="kwrd">to</span> <span class="kwrd">prepare</span> <span class="kwrd">for</span> running the <span class="kwrd">procedure</span>.    */

<span class="kwrd">PRINT</span> <span class="str">'Checking for required tables...'</span>
<span class="kwrd">IF</span> <span class="kwrd">EXISTS</span>(<span class="kwrd">SELECT</span> 1 <span class="kwrd">FROM</span> sysobjects <span class="kwrd">WHERE</span> name <span class="kwrd">IN</span> (<span class="str">'cell_opt_perm'</span>, <span class="str">'spat_idx_test_result'</span>))
    <span class="kwrd">BEGIN</span>
        <span class="kwrd">PRINT</span> <span class="str">'... The "cell_opt_perm" and "spat_idx_test_result" tables exist.'</span>
    <span class="kwrd">END</span>
<span class="kwrd">ELSE</span>
<span class="kwrd">BEGIN</span>
    <span class="kwrd">PRINT</span> <span class="str">'... Creating "cell_opt_perm" and "spat_idx_test_result" tables.'</span>
    <span class="kwrd">CREATE</span> <span class="kwrd">TABLE</span> cell_opt_perm(
        [perm_id] [<span class="kwrd">smallint</span>] <span class="kwrd">NOT</span> <span class="kwrd">NULL</span>,
        [permutation] [nvarchar](4) <span class="kwrd">NOT</span> <span class="kwrd">NULL</span>,
        [level1] [nvarchar](6) <span class="kwrd">NOT</span> <span class="kwrd">NULL</span>,
        [level2] [nvarchar](6) <span class="kwrd">NOT</span> <span class="kwrd">NULL</span>,
        [level3] [nvarchar](6) <span class="kwrd">NOT</span> <span class="kwrd">NULL</span>,
        [level4] [nvarchar](6) <span class="kwrd">NOT</span> <span class="kwrd">NULL</span>
    )

    INSERT <span class="kwrd">INTO</span> cell_opt_perm ([perm_id], [permutation], [level1], [level2], [level3], [level4])
    <span class="kwrd">VALUES</span> (1,<span class="str">'LLLL'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>),
        (2,<span class="str">'LLLM'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>),
        (3,<span class="str">'LLLH'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>),
        (4,<span class="str">'LLML'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>),
        (5,<span class="str">'LLMM'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>),
        (6,<span class="str">'LLMH'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>),
        (7,<span class="str">'LLHL'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>),
        (8,<span class="str">'LLHM'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>),
        (9,<span class="str">'LLHH'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>),
        (10,<span class="str">'LMLL'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>),
        (11,<span class="str">'LMLM'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>),
        (12,<span class="str">'LMLH'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>),
        (13,<span class="str">'LMML'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>),
        (14,<span class="str">'LMMM'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>),
        (15,<span class="str">'LMMH'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>),
        (16,<span class="str">'LMHL'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>),
        (17,<span class="str">'LMHM'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>),
        (18,<span class="str">'LMHH'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>),
        (19,<span class="str">'LHLL'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>),
        (20,<span class="str">'LHLM'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>),
        (21,<span class="str">'LHLH'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>),
        (22,<span class="str">'LHML'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>),
        (23,<span class="str">'LHMM'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>),
        (24,<span class="str">'LHMH'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>),
        (25,<span class="str">'LHHL'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>),
        (26,<span class="str">'LHHM'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>),
        (27,<span class="str">'LHHH'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>),
        (28,<span class="str">'MLLL'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>),
        (29,<span class="str">'MLLM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>),
        (30,<span class="str">'MLLH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>),
        (31,<span class="str">'MLML'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>),
        (32,<span class="str">'MLMM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>),
        (33,<span class="str">'MLMH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>),
        (34,<span class="str">'MLHL'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>),
        (35,<span class="str">'MLHM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>),
        (36,<span class="str">'MLHH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>),
        (37,<span class="str">'MMLL'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>),
        (38,<span class="str">'MMLM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>),
        (39,<span class="str">'MMLH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>),
        (40,<span class="str">'MMML'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>),
        (41,<span class="str">'MMMM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>),
        (42,<span class="str">'MMMH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>),
        (43,<span class="str">'MMHL'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>),
        (44,<span class="str">'MMHM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>),
        (45,<span class="str">'MMHH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>),
        (46,<span class="str">'MHLL'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>),
        (47,<span class="str">'MHLM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>),
        (48,<span class="str">'MHLH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>),
        (49,<span class="str">'MHML'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>),
        (50,<span class="str">'MHMM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>),
        (51,<span class="str">'MHMH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>),
        (52,<span class="str">'MHHL'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>),
        (53,<span class="str">'MHHM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>),
        (54,<span class="str">'MHHH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>),
        (55,<span class="str">'HLLL'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>),
        (56,<span class="str">'HLLM'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>),
        (57,<span class="str">'HLLH'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>),
        (58,<span class="str">'HLML'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>),
        (59,<span class="str">'HLMM'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>),
        (60,<span class="str">'HLMH'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>),
        (61,<span class="str">'HLHL'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>),
        (62,<span class="str">'HLHM'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>),
        (63,<span class="str">'HLHH'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>),
        (64,<span class="str">'HMLL'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>),
        (65,<span class="str">'HMLM'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>),
        (66,<span class="str">'HMLH'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>),
        (67,<span class="str">'HMML'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>),
        (68,<span class="str">'HMMM'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>),
        (69,<span class="str">'HMMH'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>),
        (70,<span class="str">'HMHL'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>),
        (71,<span class="str">'HMHM'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>),
        (72,<span class="str">'HMHH'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>),
        (73,<span class="str">'HHLL'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'LOW'</span>),
        (74,<span class="str">'HHLM'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'MEDIUM'</span>),
        (75,<span class="str">'HHLH'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>,<span class="str">'HIGH'</span>),
        (76,<span class="str">'HHML'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'LOW'</span>),
        (77,<span class="str">'HHMM'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'MEDIUM'</span>),
        (78,<span class="str">'HHMH'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>,<span class="str">'HIGH'</span>),
        (79,<span class="str">'HHHL'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'LOW'</span>),
        (80,<span class="str">'HHHM'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'MEDIUM'</span>),
        (81,<span class="str">'HHHH'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>,<span class="str">'HIGH'</span>)
    
    <span class="kwrd">CREATE</span> <span class="kwrd">TABLE</span> spat_idx_test_result(
        [perm_id] [<span class="kwrd">int</span>] <span class="kwrd">NOT</span> <span class="kwrd">NULL</span>,
        [num_cells] [<span class="kwrd">int</span>] <span class="kwrd">NOT</span> <span class="kwrd">NULL</span>,
        [permut] [nvarchar](4) <span class="kwrd">NOT</span> <span class="kwrd">NULL</span>,
        [g1t1] [bigint] <span class="kwrd">NULL</span>,
        [g1t2] [bigint] <span class="kwrd">NULL</span>,
        [g1t3] [bigint] <span class="kwrd">NULL</span>,
        [g1t4] [bigint] <span class="kwrd">NULL</span>,
        [g2t1] [bigint] <span class="kwrd">NULL</span>,
        [g2t2] [bigint] <span class="kwrd">NULL</span>,
        [g2t3] [bigint] <span class="kwrd">NULL</span>,
        [g2t4] [bigint] <span class="kwrd">NULL</span>
    )
    
    INSERT <span class="kwrd">INTO</span> dbo.spat_idx_test_result
    <span class="kwrd">VALUES</span> (0,16,0,<span class="kwrd">NULL</span>,<span class="kwrd">NULL</span>,<span class="kwrd">NULL</span>,<span class="kwrd">NULL</span>,<span class="kwrd">NULL</span>,<span class="kwrd">NULL</span>,<span class="kwrd">NULL</span>,<span class="kwrd">NULL</span>)
<span class="kwrd">END</span>


/*    <span class="kwrd">delete</span> <span class="kwrd">all</span> <span class="kwrd">rows</span> <span class="kwrd">from</span> "spat_idx_test_result" <span class="kwrd">table</span>. This makes it ready <span class="kwrd">to</span> stuff <span class="kwrd">in</span> <span class="kwrd">new</span> results.
    !!!WARNING!!! <span class="kwrd">if</span> your test was interupted, the <span class="kwrd">table</span> will be cleared <span class="kwrd">out</span> <span class="kwrd">and</span> the test will
    <span class="kwrd">begin</span> <span class="kwrd">from</span> the beginning. You could try <span class="kwrd">to</span> <span class="kwrd">modify</span> this <span class="kwrd">to</span> <span class="kwrd">start</span> <span class="kwrd">where</span> you <span class="kwrd">left</span> <span class="kwrd">off</span> but
    I didn<span class="str">'t have time and this worked well enough for me. */
DELETE FROM spat_idx_test_result
    WHERE perm_id != 0

/* set up counters */
DECLARE @a1 INT
DECLARE @a2 INT
DECLARE @a3 INT
DECLARE @a4 INT

/* set up variables to hold high/medium/low values and permutation to use in rebuilding
   the spatial index and recording stats */
DECLARE @lev1 VARCHAR(6)
DECLARE @lev2 VARCHAR(6)
DECLARE @lev3 VARCHAR(6)
DECLARE @lev4 VARCHAR(6)
DECLARE @permut VARCHAR(6)
DECLARE @num_cell VARCHAR(4)
DECLARE @time_str VARCHAR(20)
DECLARE @perm_id VARCHAR(20)

/* create variables to hold timestamps for beginning and ending of test queries */
DECLARE @start_t DATETIME
DECLARE @end_t DATETIME
DECLARE @elapse_t INT

/* begin looping through cell option permutations */
SET @a1 = @min_cells_per_obj
WHILE @a1 &lt;= @max_cells_per_obj
    BEGIN
        SET @a2 = 1
        PRINT '</span>Started Testing <span class="kwrd">for</span> <span class="str">' +CAST(@a1 AS VARCHAR(10)) +'</span> cells per <span class="kwrd">object</span><span class="str">'
        WHILE @a2 &lt; 82
            BEGIN
                SELECT @lev1 = level1, @lev2 = level2, @lev3 = level3, @lev4 = level4 FROM cell_opt_perm WHERE perm_id = @a2
                SET @permut = '</span><span class="str">''</span><span class="str">' +(SELECT permutation FROM cell_opt_perm WHERE perm_id = @a2) +'</span><span class="str">''</span><span class="str">'
                EXEC
                    ('</span>
                        <span class="kwrd">CREATE</span> SPATIAL <span class="kwrd">INDEX</span> <span class="str">' +@idxnm +'</span> <span class="kwrd">ON</span> <span class="str">' +@tabnm +'</span> 
                        (
                            [geom]
                        )
                        <span class="kwrd">USING</span>  GEOMETRY_GRID 
                        <span class="kwrd">WITH</span>
                            (
                                BOUNDING_BOX =(-100, -100, 300000, 650000),
                                GRIDS =(LEVEL_1 = <span class="str">' +@lev1 +'</span> ,LEVEL_2 = <span class="str">' +@lev2 +'</span> ,LEVEL_3 = <span class="str">' +@lev3 +'</span> ,LEVEL_4 = <span class="str">' +@lev4 +'</span> ), 
                                CELLS_PER_OBJECT = <span class="str">' +@a1 +'</span> ,
                                PAD_INDEX  = <span class="kwrd">OFF</span>,
                                SORT_IN_TEMPDB = <span class="kwrd">OFF</span>,
                                DROP_EXISTING = <span class="kwrd">ON</span>,
                                ALLOW_ROW_LOCKS  = <span class="kwrd">ON</span>,
                                ALLOW_PAGE_LOCKS  = <span class="kwrd">ON</span>,
                                <span class="kwrd">FILLFACTOR</span> = 100
                            )
                        <span class="kwrd">ON</span> [<span class="kwrd">PRIMARY</span>]<span class="str">'
                    )
                PRINT '</span>Re-built <span class="kwrd">index</span> <span class="kwrd">to</span> <span class="str">' +@permut
                SET @a3 = 1
                SET @a4 = 1
                WHILE @a3 &lt; 5
                    BEGIN
                        SET @start_t = GETDATE()
                        EXEC
                            (
                                '</span><span class="kwrd">CREATE</span> <span class="kwrd">TABLE</span> #tmp_tab (shp GEOMETRY)
                                <span class="kwrd">DECLARE</span> @g1 GEOMETRY
                                <span class="kwrd">SET</span> @g1 = <span class="str">' +@testgeom1 +'</span>
                                INSERT #tmp_tab (shp)
                                    <span class="kwrd">SELECT</span>
                                        r.geom <span class="kwrd">AS</span> shp
                                    <span class="kwrd">FROM</span>
                                        <span class="str">' +@tabnm +'</span> r
                                    <span class="kwrd">WHERE</span>
                                        r.geom.STIntersects(@g1) = 1
                                <span class="kwrd">DROP</span> <span class="kwrd">TABLE</span> #tmp_tab<span class="str">'
                            )
                        SET @end_t = GETDATE()
                        SET @elapse_t = (SELECT DATEDIFF(MS, @start_t, @end_t))
                        SET @num_cell = CAST(@a1 AS VARCHAR(6))
                        SET @time_str = CAST(@elapse_t AS VARCHAR(20))
                        IF @a3 = 1
                            BEGIN
                                IF (SELECT TOP 1 perm_id FROM spat_idx_test_result) IS NULL
                                    BEGIN
                                        SET @perm_id = 1
                                    END
                                ELSE
                                    BEGIN
                                        SET @perm_id = CAST((SELECT MAX(perm_id+1) FROM spat_idx_test_result) AS VARCHAR(20))
                                    END
                                EXEC
                                    (
                                        '</span>INSERT <span class="kwrd">INTO</span> spat_idx_test_result (perm_id, num_cells, permut, g1t<span class="str">' +@a3 +'</span>)
                                        <span class="kwrd">VALUES</span> (<span class="str">' +@perm_id +'</span>, <span class="str">' +@num_cell +'</span>, <span class="str">' +@permut +'</span>, <span class="str">' +@time_str +'</span>)<span class="str">'
                                    )
                            END
                        ELSE
                            EXEC
                                (
                                    '</span><span class="kwrd">UPDATE</span> spat_idx_test_result
                                    <span class="kwrd">SET</span>
                                    num_cells = <span class="str">' +@num_cell +'</span>,
                                    permut = <span class="str">' +@permut +'</span>,
                                    g1t<span class="str">' +@a3 +'</span> = <span class="str">' +@time_str +'</span>
                                    <span class="kwrd">WHERE</span> perm_id = <span class="str">' +@perm_id
                                )
                        SET @a3 = @a3 + 1
                    END
                WHILE @a4 &lt; 5
                    BEGIN
                        SET @start_t = GETDATE()
                        EXEC
                            (
                                '</span><span class="kwrd">CREATE</span> <span class="kwrd">TABLE</span> #tmp_tab (shp GEOMETRY) 
                                <span class="kwrd">DECLARE</span> @g2 GEOMETRY
                                <span class="kwrd">SET</span> @g2 = <span class="str">' +@testgeom2 +'</span>
                                INSERT #tmp_tab (shp)
                                    <span class="kwrd">SELECT</span>
                                        r.geom <span class="kwrd">AS</span> shp
                                    <span class="kwrd">FROM</span>
                                        <span class="str">' +@tabnm +'</span> r
                                    <span class="kwrd">WHERE</span>
                                        r.geom.STIntersects(@g2) = 1
                                <span class="kwrd">DROP</span> <span class="kwrd">TABLE</span> #tmp_tab<span class="str">'
                            )
                        SET @end_t = GETDATE()
                        SET @elapse_t = (SELECT DATEDIFF(MS, @start_t, @end_t))
                        SET @num_cell = CAST(@a1 AS VARCHAR(6))
                        SET @time_str = CAST(@elapse_t AS VARCHAR(20))
                        EXEC
                            (
                                '</span><span class="kwrd">UPDATE</span> spat_idx_test_result
                                <span class="kwrd">SET</span>
                                num_cells = <span class="str">' +@num_cell +'</span>,
                                permut = <span class="str">' +@permut +'</span>,
                                g2t<span class="str">' +@a4 +'</span> = <span class="str">' +@time_str +'</span>
                                <span class="kwrd">WHERE</span> perm_id = <span class="str">' +@perm_id
                            )
                        SET @a4 = @a4 + 1
                    END
                SET @a2 = @a2 + 1
            END
        SET @a1 = @a1 + 1
    END
PRINT '</span>Testing <span class="kwrd">of</span> <span class="str">' +@tabnm +'</span> spatial <span class="kwrd">index</span>: <span class="str">' +@idxnm +'</span> <span class="kwrd">is</span> complete!'
</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<p><a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/image_58.png"><img alt="image" border="0" height="170" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/image_thumb_47.png" style="margin: 0px; border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" width="244" /></a></p>
<br /><a href='https://www.esdm.co.uk/optimising-sql-server-spatial-indexing-let-sql-do-the-work'></a>&nbsp;&nbsp;<a href='https://www.esdm.co.uk/optimising-sql-server-spatial-indexing-let-sql-do-the-work'>...</a>]]></description>
      <link>https://www.esdm.co.uk/optimising-sql-server-spatial-indexing-let-sql-do-the-work</link>
      <author>()</author>
      <comments>https://www.esdm.co.uk/optimising-sql-server-spatial-indexing-let-sql-do-the-work</comments>
      <guid isPermaLink="true">https://www.esdm.co.uk/optimising-sql-server-spatial-indexing-let-sql-do-the-work</guid>
      <pubDate>Tue, 01 Oct 2013 09:11:00 GMT</pubDate>
    </item>
    <item>
      <title>Some jottings on SQL Azure and GIS</title>
      <description><![CDATA[<p>I have set up a SQL Azure 90 day trial (as of 18th November) to test whether ArcSquirrel can work with Azure. This was prompted by an email from Robert Cheetham, CEO at Azavea, who is investigating cloud solutions for their Cicero product. Here are some notes about</p>

<ol>
	<li>setting up and accessing SQL Azure databases</li>
	<li>using SQL Azure with ArcGIS + ArcSquirrel and MapLink</li>
	<li>using SQL Azure with Quantum GIS and MapServer.</li>
</ol>

<h4>Azure Management Portal</h4>

<p>Although I’ve never set up any cloud services before (other than <a href="http://www.arvixe.com/" target="_blank" title="Arvixe web site">Arvixe web hosting</a>) it was incredibly easy to setup a trial SQL Azure subscription (“Windows Azure Platform Introductory Special”), create a database, and add some firewall rules to control access. I didn’t dig deep, but the “Management Portal” seems nice and simple:</p>

<p><a href="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_10.png"><img alt="Azure Management Portal" border="0" height="188" src="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_thumb_4.png" style="padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="Azure Management Portal" width="244" />&nbsp;</a></p>

<p>It helpfully tells you your connection string for ADO.Net, ODBC and PHP (passwords not included!):</p>

<p><a href="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_8.png"><img alt="SQL Azure connection strings" border="0" height="180" src="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_thumb_3.png" style="padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="SQL Azure connection strings" width="244" />&nbsp;</a></p>

<p>See this page for <a href="http://www.microsoft.com/windowsazure/offers/popup/popup.aspx?lang=en&amp;locale=en-gb&amp;offer=ms-azr-0018p&amp;no-rewrite=true" target="_blank" title="Details of the Windows Azure Platform Introductory Special">details of the Windows Azure Platform Introductory Special</a> including what you get for no charge and the pricing for the rest.</p>

<h4>MapLink, ArcSquirrel and Azure</h4>

<p>Hartmut connected up our MapLink to the database and pushed some spatial data into my Azure database from ArcGIS – 20,000 polygons took about 75 minutes.&nbsp; Hartmut had the layers drawing in ArcMAP, performing as well as in a normal SQL Server instance apparently, with only minor mods to our code to make the initial connection. However editing will not work without some more tweaks - MapLink and ArcSquirrel rely on some SQL metadata that is a little different on Azure.</p>

<h4>SQL Server Management Studio and MS Access</h4>

<p>Connecting with SSMS is simple, however you get reduced functionality – for example you cannot right-click &gt; edit top 200 records or anything, so quick edits of a small table need to be done with SQL or in MS Access or some other client. Fortunately connecting with MS Access (ODBC + SQL Native Client 10) is also simple, and&nbsp; the Azure database behaves just like a local SQL instance – remarkable querying speed (all things considered), though slower inserts (10,000 records took something like 15 minutes). NB you cannot directly link a spatial table into Access because it doesn’t recognize the geometry data type; but to update attributes you can link a view.</p>

<p>Also, in SSMS you get no designer tools, e.g. for creating a view; everything has to be done with T-SQL.</p>

<h4>SQL Azure Database Manager</h4>

<p>After writing the above I found the database manager in the Azure control panel, which has functionality similar to SSMS, including the ability to edit the tables*:</p>

<p><a href="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_12.png"><img alt="SQL Azure database manager" border="0" height="154" src="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_thumb_5.png" style="padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="SQL Azure database manager" width="244" />&nbsp;</a></p>

<p>* spatial data types not supported for view or edit.</p>

<p>You get a designer for creating/modifying tables, but views and stored procedures are T-SQL only.</p>

<h4>MapServer, OGR and Azure</h4>

<p>Next I wanted to try serving the data through MapServer, and viewing/editing the data in Quantum GIS or MapInfo.&nbsp; MapServer and QGIS require the “geometry_columns” and “spatial_ref_sys” tables, and the easiest way to create these is to push some data in with ogr2ogr.</p>

<p>So I tried this from one of our London servers. I loaded a few hundred linear features, but got four errors like “INSERT command for new feature failed… incorrect syntax…”. On checking the results, a) while the geometries had loaded fine, all the attribute fields were NULL, and b) the spatial_ref_sys table was empty.&nbsp; I had four attribute fields, so my guess is that each syntax error was one field update across all records using a join on the incoming data.</p>

<p>Next I hooked up a MapServer WMS to my SQL Azure tables. MapServer had no trouble connecting to my Azure tables, but initially wouldn’t draw anything…&nbsp; on investigating I found that ogr2ogr had not correctly set the SRID of the geometries, so I had to update them “manually” with:</p>

<pre class="csharpcode">
<span class="kwrd">update</span> esdm_waters <span class="kwrd">set</span> ogr_geometry.STSrid = 4326</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<p>(which, incidentally, took 1 minute 52 seconds for 788 rows, demonstrating that updating an Azure database ain’t quick).</p>

<p>Clearly OGR needs a little work to do on SQL Azure support, but this was enough to get me going.</p>

<p>The WMS worked, so to challenge it a little more I set up another WMS onto a table with about 8000 sub-tidal habitat polygons, showing red in this OpenLayers map:</p>

<p><a href="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_2.png"><img alt="MapServer WMS from SQL Azure table" border="0" height="127" src="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_thumb.png" style="padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="MapServer WMS from SQL Azure table" width="244" />&nbsp;</a></p>

<p>And here showing the rivers WMS as well (blue lines):</p>

<p><a href="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_4.png"><img alt="MapServer WMS from SQL Azure table" border="0" height="127" src="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_thumb_1.png" style="padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="MapServer WMS from SQL Azure table" width="244" />&nbsp;</a></p>

<p>Performance of these two layers was perfectly acceptable, though actually about 100% slower than the same WMS working from a local SQL Server 2008 Express instance. It would be interesting to see what it could do with MapServer also running on Azure.</p>

<p>I also tried a WFS – again, performance was acceptable though significantly slower than running with a local SQL instance (though I didn’t do strict comparisons).</p>

<h4>Quantum GIS and SQL Azure</h4>

<p>I found this really helpful blog post to get started: <a href="http://woostuff.wordpress.com/2011/03/13/opening-ms-sql-spatial-in-qgis/" title="http://woostuff.wordpress.com/2011/03/13/opening-ms-sql-spatial-in-qgis/">http://woostuff.wordpress.com/2011/03/13/opening-ms-sql-spatial-in-qgis/</a></p>

<p>Adding the layers requires some python script, but I’m sure someone will write a GUI plugin for QGIS soon.</p>

<p>First make sure you are running a version of QGIS that has GDAL/OGR 1.8 libraries – I’m on 1.7.0 which is OK.</p>

<p>Open the Plugins menu &gt; Python Console</p>

<p>and type in these two commands (modified for your data):</p>

<pre class="csharpcode">
uri = <span class="str">"MSSQL:server={serverName};database={databaseName};tables={tableName};trusted_connection=yes"</span>
qgis.utils.iface.addVectorLayer(uri,<span class="str">'{yourLayerNameHere}'</span>,<span class="str">'ogr'</span>)
</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<p>In my case:</p>

<pre class="csharpcode">
uri = <span class="str">"MSSQL:server=tcp:a0awtn7gg9.database.windows.net;database=ArcSquirrel1;tables=esdm_waters;Uid=exegesis@a0awtn7gg9;Pwd=myPassword;"</span>
qgis.utils.iface.addVectorLayer(uri,<span class="rem">'Rivers','ogr')</span>
</pre>

<pre class="csharpcode">
Without any fuss my rivers dataset appeared:</pre>

<p><a href="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_14.png"><img alt="SQL Azure table in Quantum GIS" border="0" height="237" src="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_thumb_6.png" style="padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="SQL Azure table in Quantum GIS" width="244" />&nbsp;</a></p>

<p>And I can create and edit features and their attributes, here adding a test line off the Hebrides:</p>

<p><a href="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_16.png"><img alt="Editing SQL Azure features in QGIS" border="0" height="237" src="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_thumb_7.png" style="padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="Editing SQL Azure features in QGIS" width="244" />&nbsp;</a></p>

<p>And to prove it, here’s my new feature in OpenLayers…</p>

<p><a href="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_18.png"><img alt="Edited features from QGIS and SQL Azure" src="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_thumb_8.png" style="margin: 0px; width: 244px; height: 127px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="Edited features from QGIS and SQL Azure" />&nbsp;</a></p>

<p>And finally, here we have the habitat polygons (EPSG:27700) colour coded by habitat type, as well as the rivers (EPSG:4326), in QGIS. Polygon editing also worked fine, once I’d worked out why my new polygons kept vanishing (doh, classified symbols).</p>

<p><a href="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_20.png"><img alt="SQL Azure polygons thematically mapped in QGIS" border="0" height="237" src="https://www.esdm.co.uk/Data/Sites/1/Windows-Live-Writer/Some-jottings-on-SQL-Azure-and-GIS_5C47/image_thumb_9.png" style="padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="SQL Azure polygons thematically mapped in QGIS" width="244" />&nbsp;</a></p>

<p>Lots to think about, and I look forward to editing the same data with ArcGIS and ArcSquirrel soon…</p>
<br /><a href='https://www.esdm.co.uk/some-jottings-on-sql-azure-and-gis'>Crispin Flower</a>&nbsp;&nbsp;<a href='https://www.esdm.co.uk/some-jottings-on-sql-azure-and-gis'>...</a>]]></description>
      <link>https://www.esdm.co.uk/some-jottings-on-sql-azure-and-gis</link>
      <author>crispin.flower@idoxgroup.com (Crispin Flower)</author>
      <comments>https://www.esdm.co.uk/some-jottings-on-sql-azure-and-gis</comments>
      <guid isPermaLink="true">https://www.esdm.co.uk/some-jottings-on-sql-azure-and-gis</guid>
      <pubDate>Sat, 19 Nov 2011 11:42:00 GMT</pubDate>
    </item>
    <item>
      <title>Notes on importing spatial data into SQL Server 2008</title>
      <description><![CDATA[<p>
	There are a variety of ways to do this, but often you will hit issues with data validity.</p>
<ul>
	<li>
		If you have our ArcGIS Maplink product (or ArcSquirrel) then loading data in using this into a temporary SQL table is probably best as it will do a reasonable amount of checking.</li>
	<li>
		MapInfo has its own SQL loader tool ("Easy Loader" - find it in the Tool Manager)</li>
	<li>
		If you are just using open source you can use OGR2OGR</li>
</ul>
<p>
	ogr2ogr -overwrite -f "MSSQLSpatial" "MSSQL:server=MyServer;database=MyDatabase;Trusted_Connection=yes;" "C:\Temp\MyShapeFile.shp" -a_srs "EPSG:27700"</p>
<p>
	Once the data is in SQL there can still be issues:</p>
<h2>
	Incorrect SRID</h2>
<ul>
	<li>
		Make sure you specified the correct SRID when the data was loaded (if you didn’t specify it – it may well be 0). You can check this with the SQL: SELECT geom.STSrid from SitesGeom Where geom.STSrid &lt;&gt; 27700</li>
</ul>
<h2>
	Invalid ring</h2>
<ul>
	<li>
		You may also have invalid ring geometries – a good post on this is <a href="http://blogs.msdn.com/b/edkatibah/archive/2008/08/19/working-with-invalid-data-and-the-sql-server-2008-geography-data-type-part-1b.aspx"><font color="#0066cc">http://blogs.msdn.com/b/edkatibah/archive/2008/08/19/working-with-invalid-data-and-the-sql-server-2008-geography-data-type-part-1b.aspx</font></a> but the key SQL command is:</li>
</ul>
<p>
	UPDATE foo SET geom = geom.STUnion(geom.STStartPoint());</p>
<h2>
	Invalid geometries</h2>
<p>
	UPDATE foo SET geom = geom.MakeValid()</p>
<h2>
	SRID not imported</h2>
<p>
	Import geometry data into temp SQL table (e.g. foo) – with tempGeom column</p>
<p>
	Then try to populate a geometry column from the WKB of the validated column:</p>
<p>
	ALTER TABLE foo ADD geomFinal geometry;</p>
<p>
	SET geomFinal = geometry::STGeomFromWKB(geomTemp.STAsBinary(), 27700)</p>
<br /><a href='https://www.esdm.co.uk/notes-on-importing-spatial-data-into-sql-server-2008'>Crispin Flower</a>&nbsp;&nbsp;<a href='https://www.esdm.co.uk/notes-on-importing-spatial-data-into-sql-server-2008'>...</a>]]></description>
      <link>https://www.esdm.co.uk/notes-on-importing-spatial-data-into-sql-server-2008</link>
      <author>crispin.flower@idoxgroup.com (Crispin Flower)</author>
      <comments>https://www.esdm.co.uk/notes-on-importing-spatial-data-into-sql-server-2008</comments>
      <guid isPermaLink="true">https://www.esdm.co.uk/notes-on-importing-spatial-data-into-sql-server-2008</guid>
      <pubDate>Thu, 17 Nov 2011 09:24:00 GMT</pubDate>
    </item>
  </channel>
</rss>