5

I am using SQL SERVER 2012 that is running on windows datacenter 2012,

I have a database with a table that is build as followed :

[ID] (pk,int not null)
[Start] (float,null)
[End] (float, null)
[CID] (int,null) --country id

I have a web service that gets an IP, translate it to decimal (may refer to this : IP address conversion to decimal and vice versa) and request the database server for the country id

The table mentioned at first contains ~200K rows with start and end values representing IP ranges as decimal and a countryid related to each range,

I have encountered a really high CPU usage against some heavy traffic we have been dealing, so i added indexes on the start and end columns, afterwards the cpu got a little bit better but i think it should have been much more, its simply suppose to work as a search in a sorted list which should be extremely fast, though the expected result i had from adding the index were far from reality,

I suppose it is because its not searching a list but searching a range

What would be the best way to efficient this situation, since i am just sure that the resources this simple action is taking me is way to much than it should.

Here is a picture from the activity monitor now (lower traffic, after indexing) : enter image description here

This is running on Azure ExtraLarge VM (8 cores 14GB memory) - the vm is doing nothing but running a sql server with 1 table that only translates this 1 request ! the VM CPU on this lower traffic is ~30% and ~70% on higher traffic, i am sure some structure/logical changes should make a really small server\service handle this easily.

4

2 回答 2

3
SELECT TOP 1 *
FROM IP
WHERE StartIP <= yourIP
ORDER BY StartIP

This gets you the nearest IP range above the given IP. You then need to test whether the EndIP also matches. So:

SELECT *
FROM (
 SELECT TOP 1 *
 FROM IP
 WHERE StartIP <= yourIP
 ORDER BY StartIP
) x
WHERE EndIP >= yourIP

This amounts to a single-row index seek. Perfect performance.

The reason SQL Server cannot automatically do this is that it cannot know that IP ranges are ordered, meaning that the next StartIP is always greater than the current EndIP. We could have ranges of the form (100, 200), (150, 250). That is clearly invalid but it could be in the table.

于 2013-10-08T19:39:58.960 回答
0

In my opinion you main problem is the lack of "parameterization" because (a) query compilation is/can be expensive and (b) these "unparamterized" queries seems to have a lot of executions. And the available screenshot shows two things regarding this aspect:

1) The recent expensive queries aren't "parameterized".

2) High values for "Plan count":

Plan Count The number of cached query plans for this query. A large number might indicate a need for explicit query parameterization. For more information, see Specifying Query Parameterization Behavior by Using Plan Guides.

Source

So, I would try to use parameters for these queries:

SELECT TOP(1) CountryId FROM [IP] WHERE Column1 <= @param AND @param <= Column2

If you can't change the application (how SQL requests are sended to SQL Server) then you could try plan guides: http://technet.microsoft.com/en-US/library/ms191275(v=sql.90).aspx

于 2013-10-08T19:57:56.140 回答