SQL Spatial: Getting "nearest" calculations working properly

If you've ever done spatial work with SQL Server, I hope you've come across the 'nearest' problem.

You have five thousand stores around the world, and you want to identify the one that's closest to a particular place. Maybe you want the store closest to the LobsterPot office in Adelaide, at -34.925806, 138.605073. Or our new US office, at 42.524929, -87.858244. Or maybe both!

You know how to do this. You don't want to use an aggregate MIN or MAX, because you want the whole row, telling you which store it is. You want to use TOP, and if you want to find the closest store for multiple locations, you use APPLY. Let's do this (but I'm going to use addresses in AdventureWorks2012, as I don't have a list of stores). Oh, and before I do, let's make sure we have a spatial index in place. I'm going to use the default options.

And my actual query:


Great! This is definitely working. I know both those City locations, even if the AddressLine1s don't quite ring a bell. I'm sure I'll be able to find them next time I'm in the area.

But of course what I'm concerned about from a querying perspective is what's happened behind the scenes – the execution plan.


This isn't pretty. It's not using my index. It's sucking every row out of the Address table TWICE (which sucks), and then it's sorting them by the distance to find the smallest one. It's not pretty, and it takes a while. Mind you, I do like the fact that it saw an indexed view it could use for the State and Country details – that's pretty neat. But yeah – users of my nifty website aren't going to like how long that query takes.

The frustrating thing is that I know that I can use the index to find locations that are within a particular distance of my locations quite easily, and Microsoft recommends this for solving the 'nearest' problem, as described at http://msdn.microsoft.com/en-au/library/ff929109.aspx.

Now, in the first example on this page, it says that the query there will use the spatial index. But when I run it on my machine, it does nothing of the sort.


I'm not particularly impressed. But what we see here is that parallelism has kicked in. In my scenario, it's split the data up into 4 threads, but it's still slow, and not using my index. It's disappointing.

But I can persuade it with hints!

If I tell it to FORCESEEK, or use my index, or even turn off the parallelism with MAXDOP 1, then I get the index being used, and it's a thing of beauty! Part of the plan is here:


It's massive, and it's ugly, and it uses a TVF… but it's quick.

The way it works is to hook into the GeodeticTessellation function, which is essentially finds where the point is, and works out through the spatial index cells that surround it. This then provides a framework to be able to see into the spatial index for the items we want. You can read more about it at http://msdn.microsoft.com/en-us/library/bb895265.aspx#tessellation – including a bunch of pretty diagrams. One of those times when we have a much more complex-looking plan, but just because of the good that's going on.

This tessellation stuff was introduced in SQL Server 2012. But my query isn't using it.

When I try to use the FORCESEEK hint on the Person.Address table, I get the friendly error:

And I'm almost tempted to just give up and move back to the old method of checking increasingly large circles around my location. After all, I can even leverage multiple OUTER APPLY clauses just like I did in my recent Lookup post.

But this isn't friendly-looking at all, and I'd use the method recommended by Isaac Kunen, who uses a table of numbers for the expanding circles.

It feels old-school though, when I'm dealing with SQL 2012 (and later) versions. So why isn't my query doing what it's supposed to? Remember the query…

Well, I just wasn't reading http://msdn.microsoft.com/en-us/library/ff929109.aspx properly.

Let's start from the top.

1. Needs a spatial index on one of the columns that's in the STDistance call. Yup, got the index.

2. No 'PERCENT'. Yeah, I don't have that.

3. The WHERE clause needs to use STDistance(). Ok, but I'm not filtering, so that should be fine.

4. Yeah, I don't have multiple predicates.

5. The first expression in the ORDER BY is my distance, that's fine.

6. Sort order is ASC, because otherwise we'd be starting with the ones that are furthest away, and that's tricky.

7. All the rows for which STDistance returns NULL must be filtered out. But I don't have any NULL values, so that shouldn't affect me either.

…but something's wrong. I do actually need to satisfy #3. And I do need to make sure #7 is being handled properly, because there are some situations (eg, differing SRIDs) where STDistance can return NULL. It says so at http://msdn.microsoft.com/en-us/library/bb933808.aspx – "STDistance() always returns null if the spatial reference IDs (SRIDs) of the geography instances do not match." So if I simply make sure that I'm filtering out the rows that return NULL…

…then it's blindingly fast, I get the right results, and I've got the complex-but-brilliant plan that I wanted.


It just wasn't overly intuitive, despite being documented.


Nepotism In The SQL Family

There's a bunch of sayings about nepotism. It's unpopular, unless you're the family member who is getting the opportunity.

But of course, so much in life (and career) is about who you know.

From the perspective of the person who doesn't get promoted (when the family member is), nepotism is simply unfair; even more so when the promoted one seems less than qualified, or incompetent in some way. We definitely get a bit miffed about that.

But let's also look at it from the other side of the fence – the person who did the promoting. To them, their son/daughter/nephew/whoever is just another candidate, but one in whom they have more faith. They've spent longer getting to know that person. They know their weaknesses and their strengths, and have seen them in all kinds of situations. They expect them to stay around in the company longer. And yes, they may have plans for that person to inherit one day. Sure, they have a vested interest, because they'd like their family members to have strong careers, but it's not just about that – it's often best for the company as well.

I'm not announcing that the next LobsterPot employee is one of my sons (although I wouldn't be opposed to the idea of getting them involved), but actually, admitting that almost all the LobsterPot employees are SQLFamily members… …which makes this post good for T-SQL Tuesday, this month hosted by Jeffrey Verheul (@DevJef).TSQL2sDay150x150

You see, SQLFamily is the concept that the people in the SQL Server community are close. We have something in common that goes beyond ordinary friendship. We might only see each other a few times a year, at events like the PASS Summit and SQLSaturdays, but the bonds that are formed are strong, going far beyond typical professional relationships.

And these are the people that I am prepared to hire. People that I have got to know. I get to know their skill level, how well they explain things, how confident people are in their expertise, and what their values are. Of course there people that I wouldn't hire, but I'm a lot more comfortable hiring someone that I've already developed a feel for. I need to trust the LobsterPot brand to people, and that means they need to have a similar value system to me. They need to have a passion for helping people and doing what they can to make a difference. Above all, they need to have integrity.

Therefore, I believe in nepotism. All the people I've hired so far are people from the SQL community. I don't know whether I'll always be able to hire that way, but I have no qualms admitting that the things I look for in an employee are things that I can recognise best in those that are referred to as SQLFamily.

…like Ted Krueger (@onpnt), LobsterPot's newest employee and the guy who is representing our brand in America. I'm completely proud of this guy. He's everything I want in an employee. He's an experienced consultant (even wrote a book on it!), loving husband and father, genuine expert, and incredibly respected by his peers.

It's not favouritism, it's just choosing someone I've been interviewing for years.


LobsterPot Solutions in the USA

We're expanding!

I'm thrilled to announce that Microsoft Gold Partner LobsterPot Solutions has started another branch appointing the amazing Ted Krueger (5-time SQL MVP awardee) as the US lead. Ted is well-known in the SQL Server world, having written books on indexing, consulting and on being a DBA (not to mention contributing chapters to both MVP Deep Dives books). He is an expert on replication and high availability, and strong in the Business Intelligence space – vast experience which is both broad and deep.lp_usa_square

Ted is based in the south east corner of Wisconsin, just north of Chicago. He has been a consultant for eons and has helped many clients with their projects and problems, taking the role as both technical lead and consulting lead. He is also tireless in supporting and developing the SQL Server community, presenting at conferences across America, and helping people through his blog, Twitter and more.

Despite all this – it's neither his technical excellence with SQL Server nor his consulting skill that made me want him to lead LobsterPot's US venture. I wanted Ted because of his values. In the time I've known Ted, I've found his integrity to be excellent, and found him to be morally beyond reproach. This is the biggest priority I have when finding people to represent the LobsterPot brand. I have no qualms in recommending Ted's character or work ethic. It's not just my thoughts on him – all my trusted friends that know Ted agree about this.

So last week, LobsterPot Solutions LLC was formed in the United States, and in a couple of weeks, we will be open for business!

LobsterPot Solutions can be contacted via email at contact@lobsterpotsolutions.com, on the web at either www.lobsterpot.com.au or www.lobsterpotsolutions.com, and on Twitter as @lobsterpot_au and @lobsterpot_us.

Ted Kruger blogs at LessThanDot, and can also be found on Twitter and LinkedIn.

This post is cross-posted from http://lobsterpotsolutions.com/lobsterpot-solutions-in-the-usa