Il faut toujours déclarer les Foreign Key

Les contraintes d’intégrité ne servent pas seulement à vérifier l’intégrité.
Même si vous êtes sûrs de l’intégrité des données (parce que le chargement ETL le garantit par exemple), il faut déclarer les Foreign Key. C’est une information que l’on donne à l’Optimiseur sur l’état de nos données, et qui lui permettra de choisir un meilleur plan d’exécution.

La performance des chargement n’est pas une raison valable pour ne pas déclarer les foreign Key:

  • On peut choisir de ne pas valider les données existantes (NOVALIDATE) et la création de la clé étrangère sera instantanée
  • On peut choisir de ne pas vérifier les données futures (DISABLE) et les DML futurs ne seront pas pénalisés.

Mais il faut alors garantir l’intégrité des données à Oracle en mettant la contrainte en RELY et mettant le Query Rewrite à TRUSTED

La demo présente deux cas.
Un premier cas de Query Rewrite où l’utilisation de la vue matérialisée est rendue possible par la Foreign Key (soit en RELY NOVALIDATE avec query_rewrite_integrity=TRUSTED, soit en VALIDATE avec query_rewrite_integrity=enforced)
Un deuxième cas où l’optimiseur évite de faire une jointure lorsque la Foreign Key est en RELY NOVALIDATE.
Et si ce n’est pas suffisant pour justifier la création de Foreign Key en datawarehouse (où la validation est inutile vu qu’on a probablement passé des jobs de Data Quality) il faut savoir que l’optimisation STAR TRANSFORMATION sur un modèle dimensionnel ne peut se faire que si les Foreign Key vers les dimensions sont déclarées.

Bien sûr, il ne faut pas mentir à l’optimiseur, et être certain de l’intégrité de nos données. Sinon on aura un résultat faux.

Pourquoi cette demo en 11.2.0.3 ?
Je n’ai pas réussi à faire fonctionner la demo en 11.2.0.4 ni en 12.1.0.1 car le query rewrite ne se fait pas: QSM-01219: no suitable materialized view found to rewrite this query
Un SR est ouvert…

12c: faibles améliorations sur les verrous en intégrité référentielle

En 11g les verrous Row-S posés sur la table opposée lors de DML sur une table ayant un intégrité référentielle sont devenus des Row-X
Et cela a amené pas mal de régression: lorsqu’il y a des tables verrouillées en Share (à cause de foreign key non indexées) l’impact est devenu beaucoup plus important. Cette régression a été introduite pour corriger un bug: Bug 5909305 – Change to DML (TM) lock modes for foreign key constraints (Doc ID 5909305.8)

Il semble qu’en 12c ce soit un peu mieux: Certains Row-X redeviennent des Row-S, verrous légers qui ne bloquent aucun DML.

  • Sur insert dans table parente. C’est maintenant un Rows-S qui est posé sur les tables filles, comme avant la 11g
  • Lorsqu’on fait un delete sur une table fille on retrouve un Row-S sur la table parent comme avant la 11g

Par contre, on a toujours un Row-X sur la table parent lorsqu’on insert dans la table fille ou qu’on update la foreign key.

La liste complète des verrous posés par différentes opérations dans la demo.

Les explications de ces verrous dans la préz (11g): http://prezi.com/uzdd5ttg4cu0/indexing-foreign-keys-in-oracle/

Et une explication sur les modes de verrous: http://www.soug.ch/fileadmin/user_upload/Newsletter/NL_public/NL_2013_1_Award_Article.pdf et http://prezi.com/cdckwsgqxeyi/oracle-table-lock-modes/