2011-04-04 95 views
0

在這裏使用Microsoft SQL Server。 鑑於這種設置(在兩列的聚集索引):如何在多鍵索引上進行簡單範圍掃描?

use tempdb; 
CREATE TABLE mytemp 
(
    N1 INT NOT NULL, 
    N2 INT NOT NULL, 
    PRIMARY KEY (N1, N2) 
); 

INSERT mytemp (N1, N2) 
SELECT N1.number, N2.number 
FROM (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) AS N1(number) 
CROSS JOIN (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) AS N2(number) 

我怎樣才能後,即可獲取價值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 

它給了我想要的結果,但語法看起來很笨拙,它執行兩次掃描。在理論上,我認爲應該可以通過一次掃描來完成。

[編輯]我在看的掃描都SET STATISTICS IO報告的數字設置爲ON:

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

你確定你沒有錯過OR部分的幾個parens嗎? – 2011-04-04 15:55:28

+0

缺少的括號是一個意外。事實證明,預期優先順序(whew)。 – 2011-04-04 16:00:53

回答

0

基於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; 

這是草率的,而不是真的是我一直在尋找的那麼多。

0

我有一個尋道操作時,我嘗試了我的系統上。

的Microsoft SQL Server 2008(SP1) - 10.0.2531.0(X64)2009年3月29日10時11分52秒版權所有(C)1988-2008 微軟公司標準 在Windows NT版(64位) 5.2 (建設3790:Service Pack 2的) (VM)

enter image description here

+0

我沒有parens查詢得到同樣的結果:WHERE N1 = @ n1boundary AND N2> @ n2boundaryOR N1> @ n1boundary – 2011-04-04 15:55:54

+0

應該已經更清楚了。它看起來像查詢計劃中的單個查詢。但是SET STATISTICS IO輸出中的掃描和讀取次數增加了一倍(以及我正在查看的內容)。 – 2011-04-04 16:00:02

+0

我也只有1次掃描:表'mytemp'。掃描次數1,邏輯讀數2 – 2011-04-04 17:34:39

0

當我運行此我得到一個相當不錯的執行計劃這樣做只是一個聚集索引查找。

另一種選擇是,如下,使用複合鍵,但是這並聚集索引掃描,因此性能可能不是一個大表好

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) 
+0

掃描次數如下: 表'mytemp'。掃描計數1,邏輯讀取2,物理讀取0,預讀讀取0,lob邏輯讀取0,lob物理讀取0,lob預讀讀取0. – PCurd 2011-04-04 16:17:32

+0

是的,這是一個簡單的全面掃描。我正在尋找一個範圍掃描。但連接的想法是有趣的 – 2011-04-04 17:10:24