我有一个数据库,我有一个超过2米的行。它有startIpNum
和endIpNum
列(范围不重叠)。我正在对该表进行一些查询:
表:
Id | startIpNum(Numeric(0,18)) | endIpNum(Numeric(0,18)) | locId
查询1:
select locId from Blocks
where startIpNum <= 1550084098 and endIpNum >= 1550084098
查询2(添加了此查询,希望获得更好的结果):
select top 1 locId from Blocks
where endIpNum >= 1550084098
这些查询需要合理的时间,没有问题。但是每次打开网页时我都需要获得大约100个不同的行,并且需要大约15秒,这可能是预期的,但不是所希望的。
我相信通过使用索引我可以提高性能,所以我添加了2个索引,一个到start(asc)
一个到end(desc)
,但性能相同。
我还能做些什么来实现更好的查询性能?
更新
我已经运行了你们提出的create index
查询。现在没有变化。
根据要求,我在下面包含sql查询执行计划(因为我不熟悉执行计划的事情,我只是从ssms截取屏幕截图,继续询问是否需要其他东西来回答我的情况):
Query1的执行计划:
Query2的执行计划:
答案 0 :(得分:0)
如上所述,如果没有执行计划来看这个略微偏盲,但基本要点是:
1)如果索引到位以支持此查询,则添加两个没有任何意义。只能使用其中一个索引。因此,您需要一个包含两列的索引。
2)返回“*”意味着密钥查找将是不可避免的,因为使用索引来获取它需要的行,它必须从聚簇索引中获取索引中未包含的数据。如果要带回大量行,密钥查找会变得非常昂贵。如果您可以限制返回的列,则可以使用INCLUDE
来避免键查找。您不需要在此列表中包含主键,因为这仍然是索引的一部分。
说完这个,你最好的选择就是:
CREATE INDEX ix_range ON dbo.yourTable (start, end) INCLUDE (<list_of_columns_in_your_select)
查看您的查询计划,很明显,您的参数CONVERT_IMPLICIT
和@1
正在执行@2
。应避免这些,请执行以下操作:
DECLARE @1numeric numeric(18, 0),
@2numeric numeric(18, 0)
SELECT @1numeric = CAST(@1 AS numeric(18, 0)),
@2numeric = CAST(@2 AS numeric(18, 0))
SELECT locId FROM Blocks
WHERE startIpNum <= @1numeric and endIpNum >= @2numeric
答案 1 :(得分:-1)
尝试显式转换值以匹配列。
select * from that_table
where CAST(123123123 as Numeric(18,0)) between start and end
我认为由于隐式转换,sqlserver正在丢失索引查找。