web-dev-qa-db-fra.com

Les clés étrangères sont-elles indexées automatiquement dans SQL Server?

L'instruction SQL suivante créerait-elle automatiquement un index sur Table1.Table1Column ou doit-elle être créée explicitement?

Le moteur de base de données est SQL Server 2000

       CREATE TABLE [Table1] (
. . .
            CONSTRAINT [FK_Table1_Table2] FOREIGN KEY 
            (
                [Table1Column]
            ) REFERENCES [Table2] (
                [Table2ID]
            )

        )
63
Karmic Coder

SQL Server ne créera pas automatiquement un index sur une clé étrangère. Aussi à partir de MSDN:

Une contrainte FOREIGN KEY ne doit pas être liée uniquement à une contrainte PRIMARY KEY dans une autre table; il peut également être défini pour référencer les colonnes d'une contrainte UNIQUE dans une autre table. Une contrainte FOREIGN KEY peut contenir des valeurs nulles; cependant, si une colonne d'une contrainte FOREIGN KEY composite contient des valeurs nulles, la vérification de toutes les valeurs qui composent la contrainte FOREIGN KEY est ignorée. Pour vous assurer que toutes les valeurs d'une contrainte FOREIGN KEY composite sont vérifiées, spécifiez NOT NULL sur toutes les colonnes participantes.

60
jons911

En lisant la question de Mike, il demande si la contrainte FK va créer un index sur la colonne FK dans la table dans laquelle se trouve le FK (Table1). La réponse est non et généralement. (aux fins de la contrainte), il n'est pas nécessaire de le faire La colonne (s) définie comme la "CIBLE" de la contrainte, d'autre part, doit être un index unique dans la table référencée, soit une clé primaire ou une autre clé. (index unique) ou l'instruction de création de contrainte échouera.

(EDIT: ajouté pour traiter explicitement le commentaire ci-dessous -) Plus précisément, lors de la fourniture de la cohérence des données pour laquelle une contrainte de clé étrangère est là. un index peut affecter les performances d'une contrainte DRI uniquement pour les suppressions d'une ou plusieurs lignes du côté FK. Lors de l'utilisation de la contrainte, lors d'une insertion ou d'une mise à jour, le processeur connaît la valeur FK et doit vérifier l'existence d'une ligne dans la table référencée du côté PK. Il y a déjà un index. Lors de la suppression d'une ligne du côté PK, il doit vérifier qu'il n'y a pas de lignes du côté FK. Un index peut être marginalement utile dans ce cas. Mais ce n'est pas un scénario courant.

En dehors de cela, dans certains types de requêtes, cependant, lorsque le processeur de requêtes doit trouver les enregistrements du côté plusieurs d'une jointure qui utilise cette colonne de clé étrangère. joint performance is augmentée lorsqu'un index existe sur cette clé étrangère. Mais cette condition est particulière à l'utilisation de la colonne FK dans une requête de jointure, pas à l'existence de la contrainte de clé étrangère ... Peu importe si l'autre côté de la jointure est un PK ou simplement une autre colonne arbitraire. De plus, si vous devez filtrer ou ordonner les résultats d'une requête basée sur cette colonne FK, un index vous aidera ... Encore une fois, cela n'a rien à voir avec la contrainte de clé étrangère sur cette colonne.

23
Charles Bretana

Non, la création d'une clé étrangère sur une colonne ne crée pas automatiquement un index sur cette colonne. Le fait de ne pas indexer une colonne de clé étrangère entraînera une analyse de table dans chacune des situations suivantes:

  • Chaque fois qu'un enregistrement est supprimé de la table référencée (parent).
  • Chaque fois que les deux tables sont jointes sur la clé étrangère.
  • Chaque fois que la colonne FK est mise à jour.

Dans cet exemple de schéma:

CREATE TABLE MasterOrder (
   MasterOrderID INT PRIMARY KEY)

CREATE TABLE OrderDetail(
   OrderDetailID INT,
   MasterOrderID INT  FOREIGN KEY REFERENCES MasterOrder(MasterOrderID)
)

OrderDetail sera analysé chaque fois qu'un enregistrement est supprimé dans la table MasterOrder. L'ensemble du tableau OrderDetail sera également analysé chaque fois que vous rejoignez OrderMaster et OrderDetail.

   SELECT ..
   FROM 
      MasterOrder ord
      LEFT JOIN OrderDetail det
       ON det.MasterOrderID = ord.MasterOrderID
   WHERE ord.OrderMasterID = @OrderMasterID

En général, l'indexation d'une clé étrangère est bien plus l'exception que la règle.

Un cas pour ne pas indexer une clé étrangère est où elle ne serait jamais utilisée. Cela rendrait inutile la maintenance du serveur. Les tables de types peuvent tomber dans cette catégorie de temps en temps, par exemple:

CREATE TABLE CarType (
   CarTypeID INT PRIMARY KEY,
   CarTypeName VARCHAR(25)
)

INSERT CarType .. VALUES(1,'SEDAN')
INSERT CarType .. VALUES(2,'COUP')
INSERT CarType .. VALUES(3,'CONVERTABLE')

CREATE TABLE CarInventory (
   CarInventoryID INT,
   CarTypeID INT  FOREIGN KEY REFERENCES CarType(CarTypeID)
)

En faisant l'hypothèse générale que le champ CarType.CarTypeID ne sera jamais mis à jour et que la suppression d'enregistrements ne sera presque jamais, la surcharge du serveur pour maintenir un index sur CarInventory.CarTypeID serait inutile si CarInventory n'a jamais été recherché par CarTypeID.

6
David Sopko