查询索引为范围的Sql server

时间:2013-10-08 19:29:13

标签: sql sql-server performance indexing virtual-machine

我正在使用在Windows数据中心2012上运行的SQL SERVER 2012,

我有一个数据库,其中包含一个如下构建的表:

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

我有一个获取IP的Web服务,将其转换为十进制 (可以参考:IP address conversion to decimal and vice versa)并向数据库服务器请求国家/地区ID

首先提到的表包含~200K行,其开始和结束值表示IP范围为十进制,以及与每个范围相关的countryid,

我遇到了一些非常高的CPU使用率来对付我们一直处理的一些繁重的流量,所以我在开始和结束列上添加了索引,之后cpu变得更好了但是我认为应该更多,它的简单地假设在排序列表中作为搜索工作应该非常快,尽管我添加索引的预期结果远非现实,

我想这是因为它没有搜索列表而是搜索范围

有效处理这种情况的最佳方式是什么,因为我确信这个简单的行动带给我的资源远远超过了应有的程度。

以下是活动监视器中的图片(索引后流量较低): enter image description here

这是在Azure ExtraLarge VM(8核14GB内存)上运行 - 除了运行带有1个表的sql服务器之外,vm什么也没做,只能翻译这个1个请求!这个较低流量的VM CPU在流量较高时约为30%和~70%,我相信一些结构/逻辑变化应该可以使一个非常小的服务器\服务轻松处理。

2 个答案:

答案 0 :(得分:3)

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

这可以获得高于给定IP的最近IP范围。然后,您需要测试EndIP是否也匹配。所以:

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

这相当于单行索引搜索。完美的表现。

SQL Server 无法自动执行此操作的原因是它无法知道IP范围是否已排序,这意味着下一个StartIP始终大于当前EndIP。我们可以使用(100, 200), (150, 250)形式的范围。这显然是无效的,但它可能在表中。

答案 1 :(得分:0)

在我的意见中,你的主要问题是缺乏“参数化”,因为(a)查询编译是/可能是昂贵的;(b)这些“无法参与”的查询似乎有很多执行。可用的屏幕截图显示了有关此方面的两件事:

1)最近昂贵的查询不是“参数化”。

2)“计划计数”的高值:

  

计划计数此查询的缓存查询计划数。一个大的   number可能表示需要显式查询参数化。对于   有关详细信息,请参阅指定查询参数化行为   使用计划指南。

Source

所以,我会尝试为这些查询使用参数:

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

如果您无法更改应用程序(如何将SQL请求发送到SQL Server),那么您可以尝试计划指南: http://technet.microsoft.com/en-US/library/ms191275(v=sql.90).aspx