Techniques d'amélioration des performances des requêtes SQL sur les espaces de travail de la couche service de données

Les requêtes SQL sous les espaces de travail peuvent rencontrer des problèmes de performances. Les performances se dégradent généralement si la base de données n'est pas correctement gérée ou si les requêtes peuvent être réécrites plus efficacement. Outre la garantie que la base de données est correctement gérée, différentes techniques permettent d'améliorer les performances des requêtes SQL dans les espaces de travail. Si aucune technique seule ne donne de résultats significatifs, la combinaison de plusieurs techniques peut aider à améliorer de façon considérable les performances pour de nombreuses applications.
Les techniques de performance incluent :

Optimisation globale de READ SQL pour DB2Oracle et Oracle

Les règles semblent donner un meilleur temps de réponse sur DB2.

Optimisation des requêtes en fonction des pratiques recommandées en matière d'optimisation

Suivez les pratiques SQL recommandées afin de garantir une optimisation des requêtes :
  1. Indexez tous les prédicats dans des clauses JOIN, WHERE, ORDER BY et GROUP BY.

    HCL Commerce repose généralement en grande partie sur les index pour améliorer les performances SQL et l'évolutivité. Sans index appropriés, les requêtes SQL peuvent entraîner des analyses de table, ce qui impacte les performances ou génère des incidents de verrouillage. Il est recommandé d'indexer toutes les colonnes de prédicats. Seule exception : lorsque les données de colonne possèdent une très faible cardinalité.

  2. Evitez d'utiliser des fonctions dans les prédicats.
    L'index n'est pas utilisé par la base de données si la colonne comporte une fonction. Par exemple :
    
    SELECT * FROM TABLE1 WHERE UPPER(COL1)='ABC'
    
    En raison de la présence de la fonction UPPER(), l'index sur COL1 n'est pas utilisé pour les optimiseurs de base de données. OracleS'il n'est pas possible d'éviter la fonction dans le langage SQL, vous devez créer un index basé sur la fonction dans Oracle, ou bien générer des colonnes dans DB2 pour améliorer les performances.
  3. Evitez d'utiliser un caractère générique (%) en début de prédicat.
    Le prédicat LIKE '%abc' entraîne une analyse complète de la table. Par exemple :
    
    SELECT * FROM TABLE1 WHERE COL1 LIKE '%ABC'
    

    Il s'agit d'une limitation des performances connue pour toutes les bases de données.

  4. Evitez d'inclure des colonnes inutiles dans une clause SELECT.

    Indiquez les colonnes dans la clause SELECT plutôt que d'utiliser SELECT *. Les colonnes inutiles engendrent des charges supplémentaires sur le disque de la base de données, ce qui ralentit non seulement le code SQL mais la totalité du système.

  5. Lorsque cela est possible, préférez une jointure interne à une jointure externe.

    La jointure externe doit être utilisée uniquement lorsque cela est nécessaire. Elle limite en effet les options d'optimisation de la base de données, ce qui ralentit généralement l'exécution du code SQL.

  6. DISTINCT et UNION doivent être utilisés uniquement si nécessaire.

    Les opérateurs DISTINCT et UNION entraîne un tri, ce qui ralentit l'exécution du code SQL. Utilisez UNION ALL à la place de UNION, si possible, car cet opérateur est beaucoup plus efficace.

  7. OracleOracle 10g et 11g nécessite le placement des colonnes CLOB/BLOB à la fin des instructions.

    Un autre choix entraîne un arrêt anormal si la valeur en entrée dépasse les 1000 caractères.

  8. La clause ORDER BY est obligatoire dans le code SQL si vous prévoyez un ensemble de résultats triés.

    Le mot clé ORDER BY est utilisé pour trier l'ensemble de résultats en fonction des colonnes spécifiées. Sans clause ORDER BY, les résultats sont renvoyés directement sans tri d'aucune sorte. L'ordre n'est pas garanti. Soyez conscient de l'impact sur les performances causé par l'ajout de la clause ORDER BY, la base de données devant effectuer un tri de l'ensemble de résultats, ce qui entraîne l'une des opérations les plus coûteuses en terme d'exécution SQL.

Insertion de prédicats dans la clause OUTER JOIN, si possible

Pour les requêtes SQL avec la jointure externe sur l'élément de gauche (LEFT OUTER JOIN), l'insertion du prédicat de la table de droite à partir de la clause WHERE dans la condition ON permet à l'optimiseur de base de données de générer une requête plus efficace. Les prédicats de la table de gauche peuvent rester dans la clause WHERE.

De façon similaire, pour les requêtes SQL avec la jointure externe sur l'élément de droite (RIGHT OUTER JOIN), les prédicats de la table de droite doivent être déplacés depuis la clause WHERE dans la condition ON.

Par exemple, la requête suboptimale est réécrite en insérant des prédicats applicables à la table TAB_B dans la clause ON. Les prédicats spécifiques à TAB_A dans la clause WHERE peuvent y rester ou être insérés dans la clause ON :

Instruction SQL suboptimale :

SELECT TAB_A.COL1, TAB_B.COL1 FROM TAB_A LEFT OUTER JOIN TAB_B ON TAB_A.COL3 = TAB_B.COL3 WHERE TAB_A.COL1=123 AND TAB_B.COL2=456;
Instruction SQL optimisée :

SELECT TAB_A.COL1, TAB_B.COL1 FROM TAB_A LEFT OUTER JOIN TAB_B ON TAB_A.COL3 = TAB_B.COL3 AND TAB_B.COL2=456 WHERE TAB_A.COL1=123;

Les prédications des jointures internes (INNER) peuvent demeurer dans la clause WHERE. Si les tables TAB_A et TAB_B sont définies en tant que vues, l'optimiseur peut insérer ces prédicats dans les vues.

Duplication de la condition de constante pour différentes tables, si possible

Lorsque deux tables, A et B, sont jointes et qu'il existe un prédicat constant sur l'une des colonnes jointes, par exemple, A.id=B.id et A.id dans (10, 12), le prédicat constant doit être dupliqué pour la colonne jointe de la seconde table. A savoir, A.id=B.id et A.id dans (10, 12) et B.id dans (10, 12).

Par exemple, TAB_A a une relation LEFT OUTER JOIN (jointure externe gauche) avec TAB_B. S'il existe une condition spécifique à TAB_A et une condition de table croisée avec TAB_B, créez une condition supplémentaire spécifique à TAB_B en fonction de l'exigence de TAB_A et conservez les conditions de table croisée dans la clause ON :

Instruction SQL suboptimale :

SELECT TAB_A.COL1, TAB_B.COL1 FROM TAB_A LEFT OUTER JOIN TAB_B ON TAB_A.COL3 = TAB_B.COL3 WHERE TAB_A.COL1 IN (123, 456) AND TAB_B.COL2=TAB_A.COL1;
Instruction SQL optimisée :

SELECT TAB_A.COL1, TAB_B.COL1 FROM TAB_A LEFT OUTER JOIN TAB_B ON TAB_A.COL3 = TAB_B.COL3 AND TAB_B.COL2 IN (123, 456) AND TAB_B.COL2=TAB_A.COL1  WHERE TAB_A.COL1 IN (123, 456);

En particulier, si le prédicat de constante comporte uniquement la valeur 1 (par ex. : COL1=123), le deuxième prédicat doit également être converti en prédicat de constante.

Par exemple :

Instruction SQL suboptimale :

SELECT TAB_A.COL1, TAB_B.COL1 FROM TAB_A LEFT OUTER JOIN TAB_B ON TAB_A.COL3 = TAB_B.COL3 WHERE TAB_A.COL1=123 AND TAB_B.COL2=TAB_A.COL1;
Instruction SQL optimisée :

SELECT TAB_A.COL1, TAB_B.COL1 FROM TAB_A LEFT OUTER JOIN TAB_B ON TAB_A.COL3 = TAB_B.COL3 AND TAB_B.COL2=123 WHERE TAB_A.COL1=123;

Utilisation de définitions de tables imbriquées pour remplacer les vues Espace de travail

Pour améliorer les performances dans l'environnement des espaces de travail, vous pouvez utiliser des définitions de tables imbriquées pour remplacer les vues standard définies pour les tables gérées par contenu. L'exemple de requête suivant utilise les vues par défaut pour les tables CATENTRY, ATTRIBUTE et ATTRVALUE :

SELECT
     CATENTRY.CATENTRY_ID,  ATTRIBUTE.ATTRIBUTE_ID, ATTRIBUTE.NAME, ATTRIBUTE.LANGUAGE_ID, ATTRIBUTE.CATENTRY_ID,
     ATTRVALUE.ATTRVALUE_ID,  ATTRVALUE.ATTRIBUTE_ID, ATTRVALUE.CATENTRY_ID, ATTRVALUE.STRINGVALUE
FROM CATENTRY, ATTRVALUE, ATTRIBUTE
WHERE
     ATTRVALUE.CATENTRY_ID = CATENTRY.CATENTRY_ID 
     AND CATENTRY.CATENTRY_ID IN (10683)
     AND ATTRVALUE.LANGUAGE_ID IN ( -1,-2,-3,-4,-5 ) 
     AND ATTRIBUTE.LANGUAGE_ID=ATTRVALUE.LANGUAGE_ID 
     AND ATTRIBUTE.ATTRIBUTE_ID=ATTRVALUE.ATTRIBUTE_ID
ORDER BY 
     ATTRIBUTE.SEQUENCE
Cette requête peut être réécrite pour utiliser des définitions de tables imbriquées pour les tables CATENTRY, ATTRVALUE et ATTRIBUTE :

SELECT
     CATENTRY.CATENTRY_ID,  ATTRIBUTE.ATTRIBUTE_ID, ATTRIBUTE.NAME, ATTRIBUTE.LANGUAGE_ID, ATTRIBUTE.CATENTRY_ID,
     ATTRVALUE.ATTRVALUE_ID,  ATTRVALUE.ATTRIBUTE_ID, ATTRVALUE.CATENTRY_ID, ATTRVALUE.STRINGVALUE
FROM (
          SELECT 
               CATENTRY_ID
          FROM 
               DB2INST1.CATENTRY
          WHERE  NOT EXISTS (
                              SELECT '1' 
                              FROM WCW101.CATENTRY
                              WHERE DB2INST1.CATENTRY.CATENTRY_ID = WCW101.CATENTRY.CATENTRY_ID) 
          UNION ALL 
          SELECT
               CATENTRY_ID
          FROM
               WCW101.CATENTRY
          WHERE WCW101.CATENTRY.CONTENT_STATUS <> 'D'
     ) CATENTRY,
     (
          SELECT  
               ATTRVALUE_ID,LANGUAGE_ID,CATENTRY_ID,ATTRIBUTE_ID,STRINGVALUE
          FROM 
               DB2INST1.ATTRVALUE 
          WHERE  NOT EXISTS (
                              SELECT '1' 
                              FROM WCW101.ATTRVALUE 
                              WHERE DB2INST1.ATTRVALUE.ATTRVALUE_ID = WCW101.ATTRVALUE.ATTRVALUE_ID) 
          UNION ALL 
          SELECT
               ATTRVALUE_ID,LANGUAGE_ID,CATENTRY_ID,ATTRIBUTE_ID,STRINGVALUE
          FROM
               WCW101.ATTRVALUE 
          WHERE WCW101.ATTRVALUE.CONTENT_STATUS <> 'D'
     ) ATTRVALUE,  
     (
          SELECT 
               ATTRIBUTE_ID,LANGUAGE_ID,CATENTRY_ID,SEQUENCE,NAME
          FROM 
               DB2INST1.ATTRIBUTE 
          WHERE  NOT EXISTS (
                              SELECT '1' 
                              FROM WCW101.ATTRIBUTE
                              WHERE DB2INST1.ATTRIBUTE.ATTRIBUTE_ID = WCW101.ATTRIBUTE.ATTRIBUTE_ID) 
          UNION ALL 
          SELECT
               ATTRIBUTE_ID,LANGUAGE_ID,CATENTRY_ID,SEQUENCE,NAME
          FROM
               WCW101.ATTRIBUTE
          WHERE WCW101.ATTRIBUTE.CONTENT_STATUS <> 'D'
      )  ATTRIBUTE
WHERE
     ATTRVALUE.CATENTRY_ID = CATENTRY.CATENTRY_ID 
     AND CATENTRY.CATENTRY_ID IN (10683)
     AND ATTRVALUE.LANGUAGE_ID IN ( -1,-2,-3,-4,-5 ) 
     AND ATTRIBUTE.LANGUAGE_ID=ATTRVALUE.LANGUAGE_ID 
     AND ATTRIBUTE.ATTRIBUTE_ID=ATTRVALUE.ATTRIBUTE_ID
ORDER BY 
     ATTRIBUTE.SEQUENCE
Les performances peuvent parfois être augmentées en insérant des prédicats dans des définitions de tables imbriquées. Cela peut réduire la quantité de données devant être extraite pour les tables imbriquées. Dans l'exemple précédent, le prédicat LANGUAGE_ID IN ( -1,-2,-3,-4,-5 ) est inséré dans la définition de la table imbriquée ATTRVALUE dans la requête suivante :

SELECT
     CATENTRY.CATENTRY_ID,  ATTRIBUTE.ATTRIBUTE_ID, ATTRIBUTE.NAME, ATTRIBUTE.LANGUAGE_ID, ATTRIBUTE.CATENTRY_ID,
     ATTRVALUE.ATTRVALUE_ID,  ATTRVALUE.ATTRIBUTE_ID, ATTRVALUE.CATENTRY_ID, ATTRVALUE.STRINGVALUE
FROM (
          SELECT 
               CATENTRY_ID
          FROM 
               DB2INST1.CATENTRY
          WHERE  NOT EXISTS (
                              SELECT '1' 
                              FROM WCW101.CATENTRY
                              WHERE DB2INST1.CATENTRY.CATENTRY_ID = WCW101.CATENTRY.CATENTRY_ID) 
          UNION ALL 
          SELECT
               CATENTRY_ID
          FROM
               WCW101.CATENTRY
          WHERE WCW101.CATENTRY.CONTENT_STATUS <> 'D'
     ) CATENTRY,
     (
          SELECT 
               ATTRVALUE_ID,LANGUAGE_ID,CATENTRY_ID,ATTRIBUTE_ID,STRINGVALUE
          FROM 
               DB2INST1.ATTRVALUE 
          WHERE  NOT EXISTS (
                              SELECT '1' 
                              FROM WCW101.ATTRVALUE 
                              WHERE DB2INST1.ATTRVALUE.ATTRVALUE_ID = WCW101.ATTRVALUE.ATTRVALUE_ID)
               AND DB2INST1.ATTRVALUE.LANGUAGE_ID IN ( -1,-2,-3,-4,-5 )
          UNION ALL 
          SELECT
               ATTRVALUE_ID,LANGUAGE_ID,CATENTRY_ID,ATTRIBUTE_ID,STRINGVALUE
          FROM
               WCW101.ATTRVALUE 
          WHERE WCW101.ATTRVALUE.CONTENT_STATUS <> 'D' 
               AND WCW101.ATTRVALUE.LANGUAGE_ID IN ( -1,-2,-3,-4,-5 ) 
     ) ATTRVALUE,  
     (
          SELECT 
               ATTRIBUTE_ID,LANGUAGE_ID,CATENTRY_ID,SEQUENCE,NAME
          FROM 
               DB2INST1.ATTRIBUTE 
          WHERE  NOT EXISTS (
                              SELECT '1' 
                              FROM WCW101.ATTRIBUTE
                              WHERE DB2INST1.ATTRIBUTE.ATTRIBUTE_ID = WCW101.ATTRIBUTE.ATTRIBUTE_ID) 
          UNION ALL 
          SELECT
               ATTRIBUTE_ID,LANGUAGE_ID,CATENTRY_ID,SEQUENCE,NAME
          FROM
               WCW101.ATTRIBUTE
     WHERE WCW101.ATTRIBUTE.CONTENT_STATUS <> 'D'
     )  ATTRIBUTE
WHERE
     ATTRVALUE.CATENTRY_ID = CATENTRY.CATENTRY_ID 
     AND CATENTRY.CATENTRY_ID IN (10683)	
     AND ATTRIBUTE.LANGUAGE_ID=ATTRVALUE.LANGUAGE_ID 
     AND ATTRIBUTE.ATTRIBUTE_ID=ATTRVALUE.ATTRIBUTE_ID
ORDER BY 
     ATTRIBUTE.SEQUENCE
Les requêtes qui utilisent des définitions de tables imbriquées plutôt que des vues doivent explicitement faire référence aux schémas de base et d'écriture. Ces requêtes sont applicables uniquement à l'environnement d'espaces de travail et doivent donc être définies dans un modèle de requête, dans une section spéciale de gestion de contenu ('cm'). Voici un exemple de la requête précédente, définie en tant que modèle de requête pour les environnements d'exécution et d'espaces de travail :
Remarque : L'extrait suivant utilise les balises $CM:READ$, $CM:WRITE$ et $CM:BASE$. Elles sont remplacées en phase d'exécution par les noms de schéma READ, WRITE et BASE lorsque le code SQL est exécuté par la couche service de données.

Voir Modèle d'espace de données pour plus d'informations.


BEGIN_XPATH_TO_SQL_STATEMENT
     name=/CatalogEntry[CatalogEntryIdentifier[(UniqueID=)]]+IBM_Attributes
     base_table=CATENTRY

     sql=
          SELECT CATENTRY.$COLS:CATENTRY_ID$, ATTRIBUTE.$COLS:ATTRIBUTE$,ATTRVALUE.$COLS:ATTRVALUE$ 
          FROM CATENTRY, ATTRVALUE, ATTRIBUTE
          WHERE
               ATTRVALUE.CATENTRY_ID = CATENTRY.CATENTRY_ID 
               AND CATENTRY.CATENTRY_ID IN (?UniqueID?)
               AND ATTRVALUE.LANGUAGE_ID IN  ($CONTROL:LANGUAGES$) 
               AND ATTRIBUTE.LANGUAGE_ID=ATTRVALUE.LANGUAGE_ID 
               AND ATTRIBUTE.ATTRIBUTE_ID=ATTRVALUE.ATTRIBUTE_ID
          ORDER BY 
               ATTRIBUTE.SEQUENCE

     <!-- the following query is optimized for workspaces -->
     cm
     sql=
          SELECT CATENTRY.$COLS:CATENTRY_ID$, ATTRIBUTE.$COLS:ATTRIBUTE$,ATTRVALUE.$COLS:ATTRVALUE$ 
          FROM (
           SELECT 
               CATENTRY_ID
            FROM 
               $CM:BASE$.CATENTRY
            WHERE  NOT EXISTS (
                              SELECT '1' 
                              FROM $CM:WRITE$.CATENTRY
                              WHERE $CM:BASE$.CATENTRY.CATENTRY_ID = $CM:WRITE$.CATENTRY.CATENTRY_ID) 
          UNION ALL 
          SELECT
               CATENTRY_ID
          FROM
               $CM:WRITE$.CATENTRY
          WHERE $CM:WRITE$.CATENTRY.CONTENT_STATUS <> 'D'
     ) CATENTRY,
     (
          SELECT 
               ATTRVALUE_ID,LANGUAGE_ID,CATENTRY_ID,ATTRIBUTE_ID,STRINGVALUE
          FROM 
               $CM:BASE$.ATTRVALUE 
          WHERE  NOT EXISTS (
                              SELECT '1' 
                              FROM $CM:WRITE$.ATTRVALUE 
                              WHERE $CM:BASE$.ATTRVALUE.ATTRVALUE_ID = $CM:WRITE$.ATTRVALUE.ATTRVALUE_ID)
                 AND $CM:BASE$.ATTRVALUE.LANGUAGE_ID IN ($CONTROL:LANGUAGES$)
          UNION ALL 
          SELECT
               ATTRVALUE_ID,LANGUAGE_ID,CATENTRY_ID,ATTRIBUTE_ID,STRINGVALUE
          FROM
               $CM:WRITE$.ATTRVALUE 
          WHERE $CM:WRITE$.ATTRVALUE.CONTENT_STATUS <> 'D' 
                 AND $CM:WRITE$.ATTRVALUE.LANGUAGE_ID IN ($CONTROL:LANGUAGES$) 
     ) ATTRVALUE,  
     (
          SELECT 
               ATTRIBUTE_ID,LANGUAGE_ID,CATENTRY_ID,SEQUENCE,NAME
          FROM 
               $CM:BASE$.ATTRIBUTE 
          WHERE  NOT EXISTS (
                              SELECT '1' 
                              FROM $CM:WRITE$.ATTRIBUTE
                              WHERE $CM:BASE$.ATTRIBUTE.ATTRIBUTE_ID = $CM:WRITE$.ATTRIBUTE.ATTRIBUTE_ID) 
          UNION ALL 
          SELECT
               ATTRIBUTE_ID,LANGUAGE_ID,CATENTRY_ID,SEQUENCE,NAME
          FROM
               $CM:WRITE$.ATTRIBUTE
          WHERE $CM:WRITE$.ATTRIBUTE.CONTENT_STATUS <> 'D'
       )  ATTRIBUTE
     WHERE
          ATTRVALUE.CATENTRY_ID = CATENTRY.CATENTRY_ID 
          AND CATENTRY.CATENTRY_ID IN (?UniqueID?)	
          AND ATTRIBUTE.LANGUAGE_ID=ATTRVALUE.LANGUAGE_ID 
          AND ATTRIBUTE.ATTRIBUTE_ID=ATTRVALUE.ATTRIBUTE_ID
     ORDER BY 
          ATTRIBUTE.SEQUENCE

END_XPATH_TO_SQL_STATEMENT

Fractionnement des requêtes

Si l'application de ces techniques ne donne pas les améliorations de performance nécessaires, vous pouvez choisir de fractionner les requêtes qui joignent de nombreuses tables en plusieurs requêtes. L'objectif de ce fractionnement est de réduire le nombre de vues utilisées dans la jointure. Si vous fractionnez une requête à étape unique, vous devrez la convertir en requête à deux étapes, avec une ou plusieurs requêtes d'association. Lors du fractionnement de l'une des instructions SQL d'association pour une requête en deux étapes, vous devez ajouter des instructions SQL d'association supplémentaires à la définition de profil d'accès. Lorsque des requêtes sont fractionnées, vous devez utiliser des jointures internes à la place des jointures externes chaque fois que cela est possible.

Soyez prudent lorsque vous fractionnez des requêtes. Si vous utilisez trop souvent cette approche, vous risquez d'obtenir un grand nombre de requête à chaque sélection depuis une seule table. Dans ce cas, vous devrez effectuer des jointures de tables dans la mémoire en écrivant du code Java, par exemple à l'aide d'un composeur de diagramme. Dans certains cas, vous devrez fournir les résultats d'une requête dans une autre. Ces types de requête doivent être utilisés en dernier ressort, car des problèmes de maintenance, de personnalisation et de migration peuvent surgir.

Oracle

Utilisation de la syntaxe d'expression commune dans Oracle

L'Oracle optimizer génère habituellement des requêtes très efficaces, où une table temporaire est créée en fonction de l'ensemble de résultats des vues de jointure de requêtes d'origine. Une table temporaire peut être créée à l'aide de la syntaxe d'expression de table commune.

Par exemple, la requête suivante qui extrait les valeurs d'attribut du produit peut s'exécuter de façon bien plus rapide après sa réécriture à l'aide de la syntaxe d'expression de table commune :

Requête standard extrayant des attributs de produit :

BEGIN_ASSOCIATION_SQL_STATEMENT

name=IBM_CatalogEntryAttributeValue
base_table=CATENTRY

sql =
SELECT 
      CATENTRY.$COLS:CATENTRY$, ATTRVALUE.$COLS:ATTRVALUE$, 
      ATTRVALUE2.$COLS:ATTRVALUE$
FROM CATENTRY, ATTRVALUE 
JOIN ATTRIBUTE 
      ON ATTRIBUTE.LANGUAGE_ID = ATTRVALUE.LANGUAGE_ID 
      AND ATTRIBUTE.ATTRIBUTE_ID = ATTRVALUE.ATTRIBUTE_ID 
LEFT OUTER JOIN ATTRVALUE ATTRVALUE2 
      ON ATTRIBUTE.ATTRIBUTE_ID = ATTRVALUE2.ATTRIBUTE_ID 
      AND ATTRVALUE2.CATENTRY_ID = 0 
      AND ATTRIBUTE.LANGUAGE_ID = ATTRVALUE2.LANGUAGE_ID 
WHERE CATENTRY.CATENTRY_ID IN ( $ENTITY_PKS$) 
      AND ATTRVALUE.CATENTRY_ID = CATENTRY.CATENTRY_ID 
      AND ATTRVALUE.LANGUAGE_ID IN ($CTX:LANG_ID$) 

END_ASSOCIATION_SQL_STATEMENT
Utilisation de la syntaxe d'expression commune :

BEGIN_ASSOCIATION_SQL_STATEMENT

name=IBM_CatalogEntryAttributeValue
base_table=CATENTRY

sql =
WITH TEMP_TABLE AS (
SELECT 
      CATENTRY.CE_$COLS:CATENTRY$, ATTRVALUE.ATTR_$COLS:ATTRVALUE$, 
      ATTRVALUE2.ATTR2_$COLS:ATTRVALUE$
FROM CATENTRY, ATTRVALUE 
JOIN ATTRIBUTE 
      ON ATTRIBUTE.LANGUAGE_ID = ATTRVALUE.LANGUAGE_ID 
      AND ATTRIBUTE.ATTRIBUTE_ID = ATTRVALUE.ATTRIBUTE_ID 
LEFT OUTER JOIN ATTRVALUE ATTRVALUE2 
      ON ATTRIBUTE.ATTRIBUTE_ID = ATTRVALUE2.ATTRIBUTE_ID 
      AND ATTRVALUE2.CATENTRY_ID = 0 
      AND ATTRIBUTE.LANGUAGE_ID = ATTRVALUE2.LANGUAGE_ID 
WHERE CATENTRY.CATENTRY_ID IN ( $ENTITY_PKS$) 
      AND ATTRVALUE.CATENTRY_ID = CATENTRY.CATENTRY_ID 
      AND ATTRVALUE.LANGUAGE_ID IN ($CTX:LANG_ID$) 
) SELECT * FROM TEMP_TABLE

END_ASSOCIATION_SQL_STATEMENT

OracleCette technique permet à l'optimiseur d'Oracle d'insérer les prédicats nécessaires dans les vues. Comme davantage de données sont éliminées dans les premiers stades du traitement de la requête, les jointures suivantes seront appliquées à un ensemble de données bien plus petit. Cette solution permet souvent d'obtenir des améliorations notables au niveau des performances.