[MySQL] Optimisation basée sur des règles (inclut l'optimisation des sous-requêtes ; table dérivée ; table matérialisée ; semi-jointure ; sous-requête scalaire ; sous-requête de ligne)

concept

  • Table constante : la table interrogée par les deux méthodes de requête suivantes :

    • Type 1 : table de requête 一条记录都没有, ou 只有一条记录.

    • Type 2 : utilisez 主键等值匹配ou 唯一二级索引列等值匹配as 搜索条件pour interroger une table

  • Table dérivée : placée dans FROM子句后面的子查询une table appelée table dérivée.

  • Matérialisation : Le processus d'enregistrement des enregistrements dans le jeu de résultats d'une sous-requête dans une table temporaire.

  • Table matérialisée : table temporaire qui stocke le jeu de résultats d'une sous-requête .

    • Les tables matérialisées basées sur la mémoire ont des index de hachage ;

    • Les tables matérialisées sur disque ont des index arborescents B+ .

    • Étant donné que les enregistrements de la table matérialisée sont tous indexés, lors de l'utilisation de l'index pour déterminer si un opérande existe dans le jeu de résultats de sous-requête, la vitesse deviendra très rapide, améliorant ainsi les performances de l'instruction de sous-requête.

Chapitre 14 Optimisation basée sur des règles (y compris l'optimisation des sous-requêtes)

14.1 Simplification conditionnelle

  1. supprimer les parenthèses inutiles

  2. passage constant

  3. Supprimer les conditions inutiles

  4. calcul d'expression

  5. Clause HAVING et clause WHERE combinées

    • Si la fonction d'agrégation et la clause GROUP BY n'apparaissent pas dans l'instruction de requête, elles peuvent être fusionnées.
  6. Détection de table constante

    • Lorsque l'optimiseur de requête analyse une instruction de requête, il exécute d'abord une requête de table constante, puis remplace toutes les conditions impliquant la table dans la requête par des constantes, et enfin analyse les coûts de requête des autres tables.

14.2 Élimination des jointures externes

  1. La différence essentielle entre jointure externe et jointure interne :

    • Pour les enregistrements de la table de pilotage de la connexion externe, si l'enregistrement correspondant à la condition de filtre de la clause ON est introuvable dans la table pilotée, l'enregistrement de la table de pilotage sera tout de même ajouté au jeu de résultats, et chaque enregistrement de la table pilotée correspondante Le champ est renseigné avec des valeurs NULL ;

    • Cependant, si l'enregistrement de la table de pilotage de la connexion interne ne trouve pas d'enregistrement correspondant à la condition de filtre dans la clause ON de la table pilotée, l'enregistrement de la table de pilotage sera rejeté.

  2. Rejet nul (reject-NULL) : dans , l' inclusion 外连接查询spécifiée est appelée rejet nul.WHERE子句被驱动表中的列不为NULL值条件

    • C'est-à-dire : spécifiez explicitement 被驱动表的某个列la conformité IS NOT NULL, ou spécifiez implicitement 被驱动表的某个列la conformité directement 指定的值, puis la connexion externe peut être convertie en une connexion interne.

      select * from t1 left join t2 on t1.m1=t2.m2 where t2.n2 is not NULL;
      # 等价于
      select * from t1 inner join t2 on t1.m1 = t2.m2;
      
      select * from t1 left join t2 on t1.m1=t2.m2 where t2.n2 = 2;
      # 直接指定'被驱动表的某个列'符合指定的值,此时就能将 外连接 转为 内连接。
      
  3. Une fois que la clause WHERE de la table pilotée remplit la condition de rejet de valeur nulle, la jointure externe et la jointure interne peuvent être converties l'une à l'autre.

  4. Avantages : L'optimiseur sélectionne l'ordre de jointure le moins coûteux pour exécuter la requête en évaluant le coût des différents ordres de jointure des tables.

14.3 Optimisation des sous-requêtes

14.3.1 Syntaxe des sous-requêtes

  1. Les sous-requêtes peuvent apparaître à divers endroits dans une requête externe.

    • dans la clause SELECT

    • dans la clause FROM

    • dans la clause WHERE ou ON

    • Dans la clause ORDER BY et la clause GROUP BY, bien que la syntaxe le supporte, cela n'a pas de sens.

  2. Différenciez les sous-requêtes en renvoyant des ensembles de résultats :

    • Sous-requête scalaire : une sous-requête qui ne renvoie qu'une seule valeur.

    • Sous-requête de ligne : une sous-requête qui renvoie un enregistrement (un enregistrement peut contenir plusieurs colonnes).

    • Sous-requête colonne : connaître les données d'une colonne (cette colonne peut contenir plusieurs enregistrements).

    • Sous-requête de table : le résultat de la sous-requête contient de nombreux enregistrements et de nombreuses colonnes.

  3. Les sous-requêtes se distinguent par leur relation avec la requête externe :

    • Sous-requêtes non corrélées : les sous-requêtes peuvent manquer de structure indépendamment, sans dépendre de la valeur de la requête externe.

    • Sous-requête corrélée : L'exécution d'une sous-requête dépend de la valeur de la requête externe.

  4. Utilisation de sous-requêtes dans les expressions booléennes

    1. Utilisez =, >, <, >=, <=, <>, !=, <=> comme opérateurs pour les expressions booléennes

      • Remarque : La sous-requête ici ne peut être 标量子查询que ou 行子查询, c'est-à-dire que le résultat de la sous-requête ne peut renvoyer qu'une seule valeur ou ne peut être qu'un enregistrement.
       # 标量子查询
       select * from t1 where m1 < (select MIN(m2 from t2); 
       
       # 行子查询
       select * from t1 where (m1,n1)=(select m2,n2 from t2 limit 1);
      
    2. [NOT] IN / ANY / SOME / ALL sous-requêtes
      omises

    3. EXISTS sous-requête
      légèrement

  5. Considérations sur la syntaxe des sous-requêtes

    • Les sous-requêtes doivent être placées entre parenthèses.

    • Les sous-requêtes de la clause SELECT doivent être des sous-requêtes scalaires (notez qu'il ne s'agit pas de clauses from/where).

        # slect 子句中的子查询  是 标量子查询
        select (select m1, n1 from t1); 
        
        # where/from子句中的子查询 也可以是 行子查询
        ```
      
      
    • Lorsque vous souhaitez obtenir une sous-requête scalaire ou une sous-requête de ligne, mais que vous ne pouvez pas garantir que le jeu de résultats de la sous-requête ne comporte qu'un seul enregistrement, vous devez utiliser l'instruction LIMIT 1 pour limiter le nombre d'enregistrements.

    • Pour les sous-requêtes [NOT] IN / ANY / SOME / ALL, aucune instruction LIMIT n'est autorisée dans la sous-requête.

      • Remarque : Pour les sous-requêtes [NOT] IN / ANY / SOME / ALL, il est inutile d'utiliser la clause ORDER BY, la clause DISTINCT et la clause GROUP BY sans fonction d'agrégation ni clause HAVING dans la sous-requête. Étant donné que le résultat de la sous-requête est en fait une collection, peu importe que les valeurs de la collection soient triées ou non. Par exemple:

        select * from t1 where m1 in (selct m2 from t2 order by m2);
        
      • Lorsqu'il n'y a pas de fonction d'agrégation et de clause HAVING, la clause GROUP BY n'est qu'une décoration. Par exemple:

        select * from t1 where m1 in (selct m2 from t2 group by m2);
        
    • Il n'est pas autorisé d'ajouter, de supprimer ou de modifier des enregistrements d'une certaine table dans une instruction tout en effectuant une sous-requête sur la table en même temps.

14.3.2 Comment les sous-requêtes sont exécutées dans MySQL

1. Méthode d'exécution de la sous-requête scalaire et de la sous-requête de ligne

  1. Instruction de sous-requête scalaire/ligne non corrélée : exécute la requête externe et la sous-requête indépendamment (comme deux requêtes à table unique).

  2. Instructions de sous-requête scalaires/lignes corrélatives : exemple 1,

    # 例1
    select * from s1 where 
        key = (select common_field from s2 where s1.key3 = s2.key3 limit 1);
    

    Modalités de mise en œuvre :

    • Étape 1 : obtenez d'abord un enregistrement à partir de la requête externe. Dans l'exemple 1, obtenez d'abord un enregistrement de la table s1.

    • Étape 2 : Découvrez ensuite les valeurs impliquées dans la sous-requête à partir de cet enregistrement. Dans l'exemple 1, recherchez la valeur de la colonne s1.key3 à partir de l'enregistrement obtenu dans la table s1, puis exécutez la sous-requête.

    • Étape 3 : Enfin, vérifiez si la condition de la clause WHERE de la requête externe est vraie en fonction du résultat de la requête de la sous-requête. S'il est établi, ajoutez l'enregistrement de la requête externe au jeu de résultats, sinon jetez-le.

    • Étape 4 : Passez à l'étape 1 jusqu'à ce qu'aucun enregistrement ne puisse être obtenu dans la requête externe.

2. Optimisation des sous-requêtes IN

  1. Table matérialisée proposée.

    • Matérialisation : Le processus d'enregistrement des enregistrements dans le jeu de résultats d'une sous-requête dans une table temporaire.

    • Table matérialisée : table temporaire qui stocke le jeu de résultats d'une sous-requête .

      • Les tables matérialisées basées sur la mémoire ont des index de hachage ;

      • Les tables matérialisées sur disque ont des index arborescents B+ .

      • Étant donné que les enregistrements de la table matérialisée sont tous indexés, lors de l'utilisation de l'index pour déterminer si un opérande existe dans le jeu de résultats de sous-requête, la vitesse deviendra très rapide, améliorant ainsi les performances de l'instruction de sous-requête.

  2. Table matérialisée à joindre

    # 查询1
    select * from s1
    where key1 in (slecet common_field from s2 where key3 = 'a);
    
    # 当把子查询物化之后,假设子查询物化表的名称为 materialized_table, 
    # 该物化表存储的子查询结果集的列为 m_val。
      
    # 则相当于表s1与子查询物化表 materialized_table进行内连接。
    # 即,查询1 等价于 查询2
    
    # 查询2
    select s1.* from s1 
    inner join materialized_table on key1 = m_val;
    
    • Après la conversion en jointure interne, l'optimiseur de requête peut évaluer le coût des différents ordres de jointure, puis choisir le moyen le moins coûteux d'exécuter la requête.

    • Les éléments de coût de l'analyse 查询2(表s1和物化表materialized_table内连接):

      1. Si la table s1 est utilisée comme table de pilotage, le coût total de la requête est le suivant :
      • Le coût requis pour matérialiser les sous-requêtes ;

      • Le coût lors de la numérisation de la table s1 ;

      • Le nombre d'enregistrements dans la table s1 x Le coût de l'accès d'une seule table à la table materialized_table via la condition m_val=xxx (car les enregistrements de la table matérialisée ne sont pas répétés et les colonnes de la table matérialisée sont indexées, cette étape est très rapide).

      1. Si la table materialized_table est utilisée comme table de pilotage, le coût total de la requête est le suivant :
      • Le coût requis pour matérialiser les sous-requêtes ;

      • Le coût lors de la numérisation de la table matérialisée ;

      • Le nombre d'enregistrements x dans la table matérialisée Le coût d'accès à une seule table à la table s1 avec la condition clé1=xxx (cette étape est très rapide en raison de l'index construit sur la colonne clé1).

  3. Convertir une sous-requête en semi-jointure

    Après matérialisation de la sous-requête puis exécution de la requête, la création d'une table temporaire aura un coût, alors peut-on convertir directement la sous-requête en connexion sans faire de matérialisation ?

    # 查询1
    select * from s1
    where key1 in (slecet common_field from s2 where key3 = 'a);
    
    • Proposer un nouveau concept - semi-joindre

    • Remarque : la semi-jointure est optimisée pour la sous-requête IN .

    • Semi-joindre la table s1 et la table s2 signifie :

      • Pour un enregistrement dans la table s1, nous nous soucions uniquement de savoir s'il existe un enregistrement correspondant dans la table s2, mais pas du nombre d'enregistrements correspondants. Seuls les enregistrements de la table s1 sont conservés dans le jeu de résultats final.

      • # 半连接,只是在MySQL内部采用的一种执行子查询的方式,
        # MySQL没有提供面向用户的半连接语法。
        # 所以此语句不能放在黑框框中运行。
        select s1.* from s1 SEMI JOIN s2
            on s1.key1 = s2.common_field
            where key3 = 'a';
        
    • Implémenter la méthode de semi-jointure (stratégie) :

      • Extraction de table (extraction de table dans une sous-requête)

      • Duplicate Weedout (élimination des valeurs en double)

      • LooseScan (analyse lâche)

      • Matérialisation de semi-jointure

      • FirstMatch (premier match)

    • Conditions applicables pour les semi-jointures (seules les sous-requêtes qui remplissent les conditions suivantes peuvent être converties en semi-jointures)

      • La sous-requête doit être une expression booléenne composée de l'opérateur IN et figurer dans la clause WHERE ou ON de la requête de ville étrangère ;

      • La requête externe peut également avoir d'autres conditions de recherche, mais l'opérateur AND doit être utilisé pour se connecter aux conditions de recherche de la sous-requête IN ;

      • La sous-requête doit être une seule requête, et non plusieurs requêtes connectées par UNION ;

      • La sous-requête ne peut pas contenir d'instructions GROUP BY, HAVING ou de fonctions d'agrégation.

    • Ne convient pas à la semi-jointure

      • Dans la clause WHERE de la requête externe, il existe des cas où d'autres conditions de recherche sont concaténées avec des expressions booléennes composées de sous-requêtes IN à l'aide de l'opérateur OR.

      • Le cas de l'utilisation de NOT IN au lieu de IN.

      • Le cas d'une sous-requête IN dans une clause SELECT.

      • La sous-requête contient des fonctions GROUP BY, HAVING ou d'agrégation.

      • Le cas où UNION est inclus dans la sous-requête.

      • Pour les sous-requêtes non corrélées, vous pouvez essayer de les matérialiser avant de participer à la requête.

      • Une tentative de sous-requête IN peut être transformée en une sous-requête EXISTS, que la sous-requête soit corrélée ou non corrélée.

    • résumé

      • Si la sous-requête IN remplit les conditions de conversion en semi-jointure, l'optimiseur de requêtes convertit d'abord la sous-requête en semi-jointure, puis considère laquelle des cinq stratégies d'exécution de semi-jointure suivantes a le coût le plus bas, et choisissez enfin la stratégie d'exécution la moins coûteuse pour exécuter la sous-requête.

        • Extraction de table (extraction de table dans une sous-requête)

        • Duplicate Weedout (élimination des valeurs en double)

        • LooseScan (analyse lâche)

        • Matérialisation de semi-jointure

        • FirstMatch (premier match)

      • Si la sous-requête IN ne remplit pas les conditions de conversion en semi-jointure, l'optimiseur de requête trouvera un moyen moins coûteux d'exécuter la sous-requête à partir des deux stratégies suivantes :

        • Matérialisez d'abord la sous-requête, puis exécutez la requête ;

        • Effectue une conversion IN vers EXISTS.

3. Optimisation des sous-requêtes ANY / ALL

[Le transfert d'image du lien externe a échoué, le site source peut avoir un mécanisme de lien antivol, il est recommandé d'enregistrer l'image et de la télécharger directement (img-qxlXmvU4-1683462178280) (C:\Users\YUE\AppData\Roaming\marktext \images\2023-05-07-19-57-24-image.png)]

4. Exécution de la sous-requête [NOT] EXISTS

légèrement

5. Optimisation pour les tables dérivées

  1. Table dérivée : placée dans FROM子句后面的子查询une table appelée table dérivée.

  2. Pour les requêtes contenant des tables dérivées, MySQL fournit deux stratégies d'exécution.

  • matérialiser la table dérivée

    • Idée : écrire le jeu de résultats de la table dérivée dans une table temporaire interne (table matérialisée) et utiliser cette table matérialisée comme une table normale pour participer à la requête.

    • Stratégie de matérialisation différée : Lorsque la table dérivée est réellement utilisée dans la requête, elle essaiera de matérialiser la table dérivée au lieu de matérialiser la table dérivée avant d'exécuter la requête.

  • Combiner la table dérivée avec la requête externe (c'est-à-dire réécrire la requête sans la table dérivée)

——Notes de lecture, extraites de "How MySQL Works"

Je suppose que tu aimes

Origine blog.csdn.net/xiaoyue_/article/details/130547362
conseillé
Classement