Как получить простое сканирование диапазона по индексу нескольких клавиш? - PullRequest
0 голосов
/ 04 апреля 2011

Использование 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

Ответы [ 3 ]

0 голосов
/ 04 апреля 2011

Когда я запускаю это, я получаю довольно хороший план выполнения, выполняя только поиск по кластерному индексу.

Другой вариант, как показано ниже, с использованием составного ключа, но это делает кластеризованный индекс SCAN, поэтому производительность на большой таблице, вероятно, не так высока

    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 голосов
/ 04 апреля 2011

Основываясь на ответе 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 голосов
/ 04 апреля 2011

Я получил одну операцию поиска, когда попробовал ее в моей системе.

Microsoft SQL Server 2008 (SP1) - 10.0.2531.0 (X64) 29 марта 2009 г. 10:11:52 Copyright (c) 1988-2008 Microsoft Corporation Стандарт Edition (64-разрядная версия) в Windows NT 5.2 (Сборка 3790: Пакет обновления 2) (VM)

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...