2
votes

SQL Server - La création d'un index avec une contrainte unique comme l'une des colonnes est-elle nécessaire?

J'ai la requête ci-dessous:

CREATE INDEX IX_SLA_SLAName_FK_SLA_Process_IsActive ON dbo.SLA (SLAName, FK_SLA_Process, IsActive) INCLUDE (SLATimeInSeconds)

Et voici mon index pour cette table SLA .

SELECT PrimaryKey
FROM dbo.SLA
WHERE SLAName = @input
AND FK_SLA_Process = @input2
AND IsActive = 1

Cependant, la colonne SLAName est unique et a donc une contrainte / index unique. Mon index créé est-il excessif? En ai-je encore besoin ou est-ce que SQL Server utilisera l'index créé dans la colonne unique SLAName?


1 commentaires

Vous devriez vous renseigner sur la «couverture des index» pour voir quand cela peut être utile pour améliorer les performances des requêtes. Il est impossible de dire si cela aidera dans votre base de données sans plus d'informations. Vous pouvez commencer par lire cet article: mssqltips.com/sqlservertip / 3511 /…


3 Réponses :


2
votes

Ce serait un "overkill" si votre index était uniquement sur SLAName , mais vous commandez également par FK_SLA_Process et IsActive donc les requêtes qui ont besoin de colonnes bénéficieront davantage de votre index et moins si vous n'aviez que l'unique.

Donc, pour une requête comme celle-ci:

SELECT SLATimeInSeconds
FROM dbo.SLA
WHERE SLAName = 'SomeName'

Les deux index produiront les mêmes résultats et il n'y aurait aucun intérêt dans le vôtre. Mais pour des requêtes comme:

SELECT PrimaryKey
FROM dbo.SLA
WHERE SLAName = 'SomeName'
AND FK_SLA_Process = 'Some Value'

Ou

SELECT PrimaryKey
FROM dbo.SLA
WHERE SLAName = 'SomeName'

Votre index sera meilleur que l'unique (le 2ème exemple est un couvrant l'index).

Vous devriez inspecter le type de SELECT que vous faites à cette table et décider si vous en avez besoin ou non. Gardez à l'esprit que le fait d'avoir de nombreux index peut accélérer les sélections mais ralentir les insertions, les mises à jour et les suppressions.


0 commentaires

1
votes

En supposant que vous ayez une telle déclaration de table:

UNIQUE NONCLUSTERED 
(
    [SLAName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
     ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

Sous le capot, nous avons deux index:

SELECT s.ID 
FROM dbo.SLA s 
WHERE s.SLAName = 'test'
AND s.fk_SLA = 1
AND s.IsActive = 1

Donc, cette requête aura une recherche d'index et a un plan optimal:

SELECT s.ID 
FROM dbo.SLA s 
WHERE s.SLAName = 'test'

Son plan de requête indique une recherche d'index car nous recherchons par index UNIQUE NONCLUSTERED ([SLAName] ASC) code > et n'utilisez pas d'autres colonnes dans l'instruction WHERE :

 entrez la description de l'image ici

Mais si vous ajoutez un supplément paramètres dans WHERE:

CREATE TABLE [dbo].[SLA](
    [ID] [int] NOT NULL,
    [SLAName] [varchar](50) NOT NULL,
    [fk_SLA] [int] NULL,
    [IsActive] [tinyint] NULL,
PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
    ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
UNIQUE NONCLUSTERED 
(
    [SLAName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
    ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

Le plan d'exécution aura une recherche supplémentaire:

 entrez la description de l'image ici

La recherche se produit lorsque l'index ne possède pas les informations nécessaires. Le moteur de requête SQL doit sortir de la structure de données d'index UNIQUE NONCLUSTERED pour trouver les données des colonnes fk_SLA et IsActive dans votre table SLA .

Votre index est donc excessif car vous avez un index UNIQUE NONCLUSTERED :

CREATE TABLE SLA
(
   ID  INT PRIMARY KEY,
   SLAName VARCHAR(50) NOT NULL UNIQUE,
   fk_SLA INT,
   IsActive TINYINT
)


0 commentaires

0
votes

Si la colonne SLAName est unique et si elle a une contrainte unique , toute requête qui ne renvoie qu'une ou 0 ligne (toutes les requêtes avec une recherche par point qui inclut la condition SLAName = 'SomeName' ) utilisera l ' index unique et fera (au maximum) une recherche dans la table de base.

À moins que vos requêtes ne comportent une recherche par plage comme SLAName comme "SomeName%" , il n'est pas nécessaire de couvrir l'index car la recherche d'index + 1 recherche est presque la même chose que seulement recherche d'index, et il n'est pas nécessaire de gaspiller de l'espace / maintenir un autre index pour un gain de performances aussi misérable.


0 commentaires