Mysql
 sql >> Base de données >  >> RDS >> Mysql

peut-il être exécuté plus rapidement avec une grande quantité de données [MySQL]

En regardant votre EXPLAIN sortie, je craignais que votre utilisation des sous-requêtes ait entraîné une utilisation sous-optimale des index. J'ai ressenti (sans aucune justification - et là-dessus je peux très bien me tromper) que la réécriture en utilisant JOIN peut conduire à une requête plus optimisée.

Pour ce faire, nous devons comprendre ce que votre requête est destinée à faire. Cela aurait aidé si votre question l'avait articulé, mais après un petit grattage, j'ai décidé que votre requête essayait de récupérer une liste de tous les autres mots-clés qui apparaissent dans n'importe quel article contenant un mot-clé donné, avec un nombre de tous les articles dans lesquels ces mots-clés apparaissent .

Reconstruisons maintenant la requête par étapes :

  1. Récupérer "tout article contenant un mot-clé donné " (sans se soucier des doublons) :

    SELECT ca2.article_id
    FROM
           career_article_keyword AS ca2
    WHERE
          ca2.keyword_id = 9;
    
  2. Récupérer "tous les autres mots clés qui apparaissent dans [ci-dessus] "

    SELECT ca1.keyword_id
    FROM
           career_article_keyword AS ca1
      JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id)
    WHERE
          ca1.keyword_id <> 9
      AND ca2.keyword_id =  9
    GROUP BY ca1.keyword_id;
    
  3. Récupérer "[ce qui précède], ainsi que le nombre de tous les articles dans lesquels ces mots clés apparaissent "

    SELECT ca1.keyword_id, COUNT(DISTINCT ca0.article_id) AS cnt
    FROM
           career_article_keyword AS ca0
      JOIN career_article_keyword AS ca1 USING (keyword_id)
      JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id)
    WHERE
          ca1.keyword_id <> 9
      AND ca2.keyword_id =  9
    GROUP BY ca1.keyword_id
    ORDER BY cnt DESC;
    
  4. Enfin, nous voulons ajouter à la sortie le mot-clé correspondant lui-même à partir du career_keyword tableau :

    SELECT ck.keyword_id, ck.keyword, COUNT(DISTINCT ca0.article_id) AS cnt
    FROM
           career_keywords        AS ck 
      JOIN career_article_keyword AS ca0 USING (keyword_id)
      JOIN career_article_keyword AS ca1 USING (keyword_id)
      JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id)
    WHERE
          ca1.keyword_id <> 9
      AND ca2.keyword_id =  9
    GROUP BY ck.keyword_id -- equal to ca1.keyword_id due to join conditions
    ORDER BY cnt DESC;
    

Une chose qui est immédiatement claire est que votre requête d'origine faisait référence à career_keywords deux fois, alors que cette requête réécrite ne fait référence qu'une seule fois à cette table ; cela seul peut expliquer la différence de performances - essayez de supprimer la deuxième référence (c'est-à-dire là où elle apparaît dans votre première sous-requête), car elle est entièrement redondante.

En revenant sur cette requête, nous pouvons voir que des jointures sont effectuées sur les colonnes suivantes :

  • career_keywords.keyword_id dans ck JOIN ca0

    Ce tableau définit la PRIMARY KEY (`keyword_id`) , il existe donc un bon index qui peut être utilisé pour cette jointure.

  • career_article_keyword.article_id dans ca1 JOIN ca2

    Ce tableau définit UNIQUE KEY `article_id` (`article_id`,`keyword_id`) et, depuis article_id est la colonne la plus à gauche de cet index, il existe un bon index qui peut être utilisé pour cette jointure.

  • career_article_keyword.keyword_id dans ck JOIN ca0 et ca0 JOIN ca1

    Aucun index ne peut être utilisé pour cette jointure :le seul index défini dans cette table a une autre colonne, article_id à gauche de keyword_id - donc MySQL ne peut pas trouver keyword_id entrées dans l'index sans connaître au préalable l'article_id . Je vous suggère de créer un nouvel index qui a keyword_id comme sa colonne la plus à gauche.

    (La nécessité de cet index aurait également pu être déterminée directement en examinant votre requête d'origine, où vos deux requêtes les plus externes effectuent des jointures sur cette colonne.)