SQL Server equivalente à cláusula Oracle USING INDEX

9

Existe um equivalente do SQL Server 2008 da cláusula USING INDEX no Oracle? Especificamente para a construção:

CREATE TABLE c(c1 INT, c2 INT);
CREATE INDEX ci ON c (c1, c2);
ALTER TABLE c ADD CONSTRAINT cpk PRIMARY KEY (c1) USING INDEX ci;

Na documentação do Sql Server sobre índices exclusivos , afirma (ênfase adicionada):

Índices exclusivos são implementados das seguintes maneiras:

PRIMARY KEY ou UNIQUE constrangimento

Quando você cria uma restrição PRIMARY KEY, um índice clusterizado exclusivo na coluna ou colunas é criado automaticamente se um índice clusterizado da tabela ainda não existir e você não especificar um índice não clusterizado exclusivo . A coluna da chave primária não pode permitir valores NULL.

O que parece implicar que há uma maneira de especificar qual índice deve ser usado para uma chave primária.

nik
fonte
Apenas defina o PK junto com a tabela. create table c (c1 int not null primary key, c2 int)
precisa saber é o seguinte
É a "fazer um uso PK um índice chamado" parte que eu estou interessado.
nik
Não, não há como fazer isso. Uma chave primária é uma restrição e um índice. No que você forneceu, a chave primária seria, por padrão, um índice clusterizado exclusivo. O que tornaria o outro índice definido uma duplicata, a menos que você incluísse c1 e c2 na cláusula where.
Aaron

Respostas:

7

Existe um equivalente do SQL Server 2008 da cláusula USING INDEX no Oracle?

Não. Quando você cria uma chave primária ou restrição exclusiva no SQL Server, um índice exclusivo para oferecer suporte a essa restrição é criado automaticamente, com as mesmas chaves.

O que parece implicar que há uma maneira de especificar qual índice deve ser usado para uma chave primária.

Não. A documentação está apenas tentando explicar se o índice de suporte automático será criado como clusterizado ou não clusterizado, se você não especificar. É confuso, eu concordo.

Para esclarecer, quando você adiciona uma restrição de chave primária a uma tabela existente sem expressar uma preferência, o índice de suporte será armazenado em cluster se não houver um índice em cluster preexistente na tabela. O índice de suporte será criado como não clusterizado se já houver um índice em cluster

Você pode solicitar especificamente uma chave primária em cluster ou não em cluster usando: PRIMARY KEY CLUSTEREDou PRIMARY KEY NONCLUSTERED.

Para ser justo, a documentação é muito mais clara sobre o assunto em:

restrição de tabela (Transact-SQL)

Paul White 9
fonte
5

A sintaxe do SQL Server para criar um índice em cluster que também é uma chave primária é:

CREATE TABLE dbo.c
(
    c1 INT NOT NULL, 
    c2 INT NOT NULL,
    CONSTRAINT PK_c
    PRIMARY KEY CLUSTERED (c1, c2)
);

No que diz respeito ao seu comentário: "fazendo uma PK usar um índice nomeado", o código acima resultará no índice da chave primária chamado "PK_c".

A chave primária e a chave de cluster não precisam ser as mesmas colunas. Você pode defini-los separadamente. No exemplo acima, altere a CLUSTEREDpalavra-chave para NONCLUSTEREDe simplesmente adicione um índice em cluster usando a CREATE INDEXsintaxe:

CREATE TABLE dbo.c
(
    c1 INT,
    c2 INT,
    CONSTRAINT PK_c
    PRIMARY KEY NONCLUSTERED (c1, c2)
);

CREATE CLUSTERED INDEX CX_c ON dbo.c (c2);

No SQL Server, o índice clusterizado é a tabela, eles são um e o mesmo. Um índice em cluster define a ordem lógica das linhas armazenadas na tabela. No meu primeiro exemplo, as linhas são armazenadas na ordem dos valores das colunas c1e c2. Como a chave de cluster também é definida como a chave primária, a combinação de c1e c2deve ser exclusiva em toda a tabela.

No segundo exemplo, a chave primária é composta pelas colunas c1e c2, no entanto, a chave de cluster é apenas a c2coluna. Como não especifiquei o UNIQUEatributo na CREATE INDEXinstrução, a chave de cluster ( c2) não precisa ser exclusiva na tabela. Um "uniquificador" será criado automaticamente pelo SQL Server e anexado aos valores na c2coluna para criar a chave de cluster. Essa chave de cluster, como agora é exclusiva, será usada como um ID de linha em outros índices criados na tabela.

Para provar que a chave de cluster controla o layout das linhas no armazenamento, você pode usar a função não documentada fn_PhysLocCracker(%%PHYSLOC%%). O código a seguir mostra as linhas são dispostas em disco na ordem da c2coluna, que defini como a chave de cluster:

USE tempdb;

CREATE TABLE dbo.PKTest
(
    c1 INT NOT NULL
    , c2 INT NOT NULL
    , c3 VARCHAR(256) NOT NULL
);

ALTER TABLE PKTest 
ADD CONSTRAINT PK_PKTest 
PRIMARY KEY NONCLUSTERED (c1, c2);

CREATE CLUSTERED INDEX CX_PKTest 
ON dbo.PKTest(c2);

TRUNCATE TABLE dbo.PKTest;

INSERT INTO dbo.PKTest (c1, c2, c3)
SELECT TOP(25) o1.object_id / o2.object_id, o2.object_id, o1.name + '.' + o2.name
FROM sys.objects o1
    , sys.objects o2
WHERE o1.object_id >0 
    and o2.object_id > 0;

SELECT plc.file_id
    , plc.page_id
    , plc.slot_id
    , pk.*
FROM dbo.PKTest pk
CROSS APPLY fn_PhysLocCracker(%%PHYSLOC%%) plc;

Os resultados do meu tempdb são:

insira a descrição da imagem aqui

Na imagem acima, as três primeiras colunas são produzidas a partir da fn_PhysLocCrackerfunção, mostrando a ordem física das linhas no disco. Você pode ver que o slot_idvalor aumenta a etapa de bloqueio com o c2valor, que é a chave de cluster. O índice de chave primária armazena linhas em uma ordem diferente, o que pode ser visto forçando o SQL Server a retornar resultados da verificação da chave primária:

SELECT pkt.c1
    , pkt.c2
FROM dbo.PKTest pkt WITH (INDEX = PK_PKTest, FORCESCAN);

Observe que não usei uma ORDER BYcláusula na instrução acima, pois estou tentando mostrar a ordem dos itens no índice de chave primária.

A saída da consulta acima é:

insira a descrição da imagem aqui

Olhando para a fn_PhysLocCrackerfunção, podemos ver a ordem física do índice da chave primária.

SELECT plc.file_id
    , plc.page_id
    , plc.slot_id
    , pkt.c1
    , pkt.c2
FROM dbo.PKTest pkt WITH (INDEX = PK_PKTest, FORCESCAN)
CROSS APPLY fn_PhysLocCracker(%%PHYSLOC%%) plc;

Como estamos lendo exclusivamente do próprio índice, ou seja, nenhuma coluna fora do índice está sendo referenciada na consulta, os %%PHYSLOC%%valores representam as páginas no próprio índice.

Os resultados:

insira a descrição da imagem aqui

Max Vernon
fonte