Index non clusterisés - clés et non-clés

8

Je veux juste m'assurer que je suis sur la bonne voie avec ces concepts, donc tout commentaire serait grandement apprécié.

Voici ma théorie de la requête que je viens d'optimiser, à travers un processus d'essais et d'erreurs et la lecture de la documentation MSDN.

La requête

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)

L'index

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

Il y a aussi un index PK sur pic_id

La théorie

Les colonnes clés le sont, car elles sont utilisées dans une clause WHERE (mais pas dans une situation OR) ou dans ORDER BY.

Les colonnes non clés (INCLUDE) en tant que telles, car elles sont utilisées dans le WHERE, mais parce qu'elles sont utilisées dans un scénario OU, elles ne peuvent pas (ne peuvent pas = n'améliorer pas les performances) être une colonne clé.

Ces présomptions sont-elles correctes? Sinon, que me manque-t-il?

Merci!

Darthtong
la source

Réponses:

8

Vous demandez à l'optimiseur de requêtes de produire un plan pouvant répondre à la requête:

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

Le reste est duvet (y compris le OR pic_id = @pic_id). Ce sera un scan de table, garanti, en raison de la faible sélectivité des prédicats impliqués (je suis sûr deletedet hiddensont 0/1, et map_ipje doute que cela ait un impact significatif). Le seul prédicat qui pourrait enregistrer la requête est, pic_id = @pic_idmais en le plaçant dans une condition OR, vous avez tué sa chance. Aucun indice secondaire ne peut l'aider, de façon réaliste. L'ajout de ROW_NUMBER entraînera une sorte de tri, très probablement, mais le véritable dommage est l'analyse.

C'est une cause perdue. Trouvez des exigences réalistes.

Remus Rusanu
la source
6

La clé primaire est-elle également l'index cluster? Si tel est le cas, il n'y a aucune raison de le faire INCLUDE (pic_id)car l'index cluster unique sera déjà utilisé comme signet dans l'index non cluster.

En ce qui concerne ce dont vous parlez avec le bloc opératoire, il s'agit en fait d'une deuxième partie du WHERE, mais vous comptez simplement sur la sélectivité du premier pour effectuer la majeure partie du travail (tout en vous appuyant sur l'INCLURE pour éviter d'aller à la table).

Mais en y ayant *, vous devrez peut-être quand même aller à la table.

D'un autre côté, je ne suis peut-être pas en train de concevoir mes index sur la base d'une seule requête, à moins que cette requête ne soit très utilisée sans prendre davantage en compte la charge. Et toujours regarder le plan d'exécution ne pouvait pas faire de mal.

Cade Roux
la source