Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何对多键索引进行简单的范围扫描?_Sql Server_Tsql - Fatal编程技术网

Sql server 如何对多键索引进行简单的范围扫描?

Sql server 如何对多键索引进行简单的范围扫描?,sql-server,tsql,Sql Server,Tsql,在此处使用Microsoft SQL Server。 给定此设置(两列上的聚集索引): 如何获得n1=5,n2=6之后的值(按n1,n2排序时)?我有以下的尝试 declare @n1boundary int = 5; declare @n2boundary int = 6; SELECT N1, N2 FROM mytemp WHERE N1 = @n1boundary AND N2 > @n2boundary OR N1 > @n1boundary ORDER BY N1, N

在此处使用Microsoft SQL Server。 给定此设置(两列上的聚集索引):

如何获得n1=5,n2=6之后的值(按n1,n2排序时)?我有以下的尝试

declare @n1boundary int = 5;
declare @n2boundary int = 6;

SELECT N1, N2
FROM mytemp
WHERE N1 = @n1boundary AND N2 > @n2boundary
OR N1 > @n1boundary
ORDER BY N1, N2
它给出了我想要的结果,但是语法看起来很笨拙,它执行了两次扫描。在我看来,从理论上讲,用一次扫描就可以做到这一点

[编辑]我正在查看的扫描是在“设置统计信息IO”设置为“开”时报告的扫描:

Table 'mytemp'. Scan count 2, logical reads 4

我在我的系统上尝试了一次搜索操作

Microsoft SQL Server 2008(SP1)- 10.0.2531.0(X64)2009年3月29日10:11:52版权所有(c)1988-2008 微软公司标准 Windows NT 5.2上的版本(64位) (构建3790:Service Pack 2) (虚拟机)


当我运行这个程序时,我得到了一个相当好的执行计划,只需执行聚集索引搜索

另一个选项如下所示,使用复合键,但这会进行聚集索引扫描,因此在大型表上性能可能不太好

    declare @n1boundary int = 5;
    declare @n2boundary int = 6;

    select N1, N2
    from mytemp 
    where cast(N1 as varchar(2))+cast((N2-1) as varchar(2)) >
 cast(cast(@n1boundary as varchar(2))+cast((@n2boundary-1) as varchar(2)) as int)

根据PCurd的回答,这里有另一个奇怪的解决方法。它保持聚集索引的串联,为其编制索引,然后对其执行简单的范围扫描:

ALTER TABLE mytemp
ADD stringify as 
    right('00' + cast(n1 as varchar), 2) +
    right('00' + cast(n2 as varchar), 2) PERSISTED;

CREATE NONCLUSTERED INDEX ix_mytemp 
ON mytemp(stringify)
INCLUDE (n1, n2)

declare @n1boundary int = 5;
declare @n2boundary int = 6;

SELECT n1, n2
FROM mytemp
WHERE stringify > 
    right('00' + cast(@n1boundary as varchar), 2) +
    right('00' + cast(@n2boundary as varchar), 2) 
ORDER BY stringify;

这是草率的,也不是我想要的。

你确定你没有因为或部分而遗漏几个括号吗?缺少括号是个意外。事实证明,优先级是预期的(whew)。对于没有参数的查询,我得到了相同的结果:其中N1=@n1boundary和N2>@n2boundary或N1>@n1boundary应该更清楚。它看起来像查询计划中的单个搜索。但是SET STATISTICS IO输出中的扫描和读取次数增加了一倍(这也是我现在看到的)。扫描计数1,逻辑读取2扫描计数如下:表“mytemp”。扫描计数1,逻辑读取2,物理读取0,预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。是的,这是一个简单的完全扫描。我在找范围扫描。但是串联的想法很有趣
ALTER TABLE mytemp
ADD stringify as 
    right('00' + cast(n1 as varchar), 2) +
    right('00' + cast(n2 as varchar), 2) PERSISTED;

CREATE NONCLUSTERED INDEX ix_mytemp 
ON mytemp(stringify)
INCLUDE (n1, n2)

declare @n1boundary int = 5;
declare @n2boundary int = 6;

SELECT n1, n2
FROM mytemp
WHERE stringify > 
    right('00' + cast(@n1boundary as varchar), 2) +
    right('00' + cast(@n2boundary as varchar), 2) 
ORDER BY stringify;