Índices não agrupados - chaves e não chaves

8

Eu só quero ter certeza de que estou no caminho certo com esses conceitos, para que qualquer feedback seja muito apreciado.

Aqui está minha teoria a partir da consulta que acabei de otimizar, através de um processo de tentativa e erro e lendo a documentação do MSDN.

A pergunta

DECLARE @pic_id int
SET pic_id = 1

SELECT ROW_NUMBER() OVER (ORDER BY pic_date desc) AS row_num, *
FROM tbl_pics
WHERE deleted = 0 AND map_id = 1 AND (hidden = 0 OR pic_id = @pic_id)

O índice

CREATE NONCLUSTERED INDEX [IX_tbl_pics] ON [dbo].[tbl_pics] 
(
    [map_id] ASC,
    [deleted] ASC,
    [pic_date] DESC
)
INCLUDE ( [hidden], [pic_id] )

Há também um índice PK em pic_id

A teoria

As colunas-chave são verdadeiras, porque são usadas em uma cláusula WHERE (mas não em uma situação OR) ou em ORDER BY.

As colunas nonkey (INCLUDE) são assim, porque são usadas no WHERE, mas porque são usadas em um cenário OR, não podem (não podem = não melhorarão o desempenho) ser uma coluna-chave.

Essas presunções estão corretas? Se não, o que estou perdendo?

Obrigado!

Darthtong
fonte

Respostas:

8

Você está solicitando ao otimizador de consulta que produza um plano que possa responder à consulta:

SELECT *
FROM tbl_pics
WHERE deleted = 0 AND map_id = 1 AND hidden = 0;

O resto é fofo (incluindo o OR pic_id = @pic_id). Esta será uma varredura da tabela, garantido, por causa da baixa seletividade dos predicados envolvidos (eu tenho certeza deletede hiddensão 0/1, e map_ipduvido que tenha qualquer impacto significativo). O único predicado que poderia salvar a consulta é pic_id = @pic_idcolocá-la em uma condição OR que você matou. Nenhum índice secundário pode ajudá-lo, realisticamente. A adição de ROW_NUMBER terá uma classificação, provavelmente, mas o dano real é a verificação.

Esta é uma causa perdida. Crie requisitos realistas.

Remus Rusanu
fonte
6

A chave primária também é o índice em cluster? Nesse caso, não há razão para isso, INCLUDE (pic_id)porque o índice clusterizado exclusivo já será usado como marcador no índice não clusterizado.

Quanto ao que você está falando com o OR, essa é efetivamente uma segunda parte do WHERE, mas você está apenas confiando na seletividade do primeiro a fazer a maior parte do trabalho (enquanto confia no INCLUDE para evitar ir ao a mesa).

Mas ao ter * lá, você pode ter que ir para a mesa de qualquer maneira.

Por outro lado, talvez eu não esteja projetando meus índices com base em uma única consulta, a menos que essa consulta seja muito usada sem levar em conta mais da carga. E ainda dando uma olhada no plano de execução não poderia machucar.

Cade Roux
fonte