web-dev-qa-db-fra.com

Différences de performance entre la recherche clé de la recherche RID LookUp vs?

Existe-t-il des différences de performance entre lorsqu'un indice non en cluster utilise la clé de l'index en cluster pour localiser la ligne VS lorsque ce tableau n'a pas d'index en cluster et l'index non clusterné localise la ligne via le RID?

Est-ce que différents niveaux de fragmentation ont également une incidence sur cette comparaison de performance? (E.G. Dans les deux scénarios, les tables sont 0% fragmentées, vs 50%, vs 100%.)

2
J.D.

En laissant de côté la fragmentation bogeyeman (peu importe lorsque vous faites des recherches singleton), la principale différence est qu'un débard spécifie la page exacte une ligne est activée, tandis qu'avec une recherche de clé, vous traversez les niveaux de non-feuille de l'index en cluster. trouver la page cible. Aaron Bertrand a fait des tests à ce sujet dans est une recherche rrup plus rapidement qu'une recherche clé?

Toutefois, les tas peuvent avoir transfert transféré (ou enregistrements en eux, auquel cas plusieurs iOS logiques sont nécessaires pour trouver la ligne cible.

Je blogué à ce sujet récemment , et je reproduit le contenu ici pour éviter une réponse de commentaire.

CREATE TABLE el_heapo 
( 
    id INT IDENTITY, 
    date_fudge DATE, 
    stuffing VARCHAR(3000)
);

INSERT dbo.el_heapo WITH (TABLOCKX) 
      ( date_fudge, stuffing )
SELECT DATEADD(HOUR, x.n, GETDATE()), REPLICATE('a', 1000)
FROM (
SELECT TOP (1000 * 1000)
ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM sys.messages AS m
CROSS JOIN sys.messages AS m2
) AS x (n)

CREATE NONCLUSTERED INDEX ix_heapo ON dbo.el_heapo (date_fudge);

Nous pouvons regarder la table avec sp_blitzindex

EXEC master.dbo.sp_BlitzIndex @DatabaseName = N'Crap', 
                              @SchemaName = 'dbo', 
                              @TableName = 'el_heapo';

NUTS

Cette requête produira des sauvegardes de signets.

SELECT *
FROM dbo.el_heapo AS eh
WHERE eh.date_fudge BETWEEN '2018-09-01' AND '2019-09-01'
AND 1 = (SELECT 1)
OPTION(MAXDOP 1);

NUTS

Nous pouvons maintenant causer des enregistrements transférés:

UPDATE eh
SET eh.stuffing = REPLICATE('z', 3000)
FROM dbo.el_heapo AS eh
WHERE eh.date_fudge BETWEEN '2018-09-01' AND '2019-09-01'
OPTION(MAXDOP 1)

Blitzindex va nous montrer à nous:

NUTS

Et si nous réexécutons la requête de recherche:

NUTS

Le profileur montrera également une différence:

NUTS

8
Erik Darling

N'oubliez pas que la traversée des niveaux non-feuillets de l'indice en cluster (qui est essentiellement ce qui diffère une clé d'une recherche rruptique) sera presque tous en mémoire. SQL Server se lit sur la racine, le niveau suivant, etc. à nouveau, encore et encore, etc. En d'autres termes, ils seront super chauds.

Comparer cela aux enregistrements transférés dans un tas. Vous pensez que vous avez trouvé une rangée, mais dar, c'est ailleurs. Vous, pour ainsi dire, sautez partout. Donc, il convient de veiller à ce que je viens de regarder "Lit" ici. Logical VS Lectures physiques devient un facteur.

Et, bien sûr, un aspect très important est que si vous avez des records transférés en tas en premier lieu! Sys.dm_db_index_physical_stats avec option détaillée vous dira.

1
Tibor Karaszi