0
votes

MySQL Plusieurs indexations ne fonctionnent pas pour une seule requête (groupe par + la plage de l'état)

J'ai une requête comme ci-dessous: xxx

et j'ai 2 index sur keyword_report; xxx

expliquer le format = JSON Résultat: xxx

dans le tableau, il y a environ;

  • 1000 Org_id distinct,
  • 500 Distinct Report_Date,
  • 30 pays distincts,
  • 10 millions de mots clés_id_id.

    Je ne pouvais pas comprendre deux choses ici.

    1. Pourquoi est-ce qu'il utilise temporaire?

    2. Pourquoi les index multiples ne fonctionnent pas?

      En conséquence, comment puis-je l'améliorer?


1 commentaires

"Comment puis-je l'améliorer?" - Que voulez-vous améliorer? Est-ce trop lent pour vous? Combien de lignes correspondent à l'endroit où les conditions? Et combien de lignes obtenez-vous après le groupe?


3 Réponses :


0
votes

La sortie JSON suivante semble indiquer que votre indice index1 est utilisé: xxx

Cet index peut être utilisé pendant le CLAUSE Pour filtrer les enregistrements non correspondants. Après cela, MySQL doit toujours effectuer un groupe d'agrégation , qui inclut une somme sur la colonne impressions . Notez qu'un index n'entraidera pas vraiment beaucoup pour l'agrégation, car, par définition, la base de données doit toucher chaque enregistrement, dans chaque groupe, pour calculer la somme. Bien que la plupart du temps, une base de données ne choisira même pas d'utiliser deux indices différents sur la même table (mais cela est possible), dans ce cas, le second index2 indexé ne vous aiderait pas beaucoup ici à cause de la Nature de votre agrégation.

Pour donner un exemple dans lequel vous pourriez utiliser un seul index pour couvrir toutes les étapes de la requête, considérez les éléments suivants: xxx

Maintenant, si vous avez défini l'index suivant: xxx

alors mySQL pourrait choisir de l'utiliser. Cela fonctionnerait car, après filtration des enregistrements de désactivation dans la clause , il serait facile de trouver la valeur max de impressions pour chaque pays.


3 commentaires

MySQL s'arrêtera à reporting_date Condition de gamme de rencontres Malheureusement . Ainsi, la suggestion d'index ne fonctionnera pas.


reporter_date est une plage, alors après rapport_date, votre index (org_id, rapport_date, pays, impressions) ne fonctionne pas?


@Sha je suggère cet index pour une requête différente, pas celle que vous avez présentée dans votre question. Pour ce que vous avez présenté, index1 pourrait être aussi bon que possible.



0
votes

Pourquoi plusieurs index ne fonctionnent pas?

mysql utilise rarement plus d'un index à la fois, sauf s'il y a une possibilité de index_merge , lors de l'utilisation de ou conditions, etc. Dans ce cas particulier, la première priorité est Pour condition, c'est pourquoi il utilise le index1 car il peut réduire les recherches de données par PIN-pointage sur des lignes spécifiques à regarder en utilisant l'index. Aussi, logiquement, se produit avant groupe par , et il aide également à réduire les données à l'agrégat sur (au lieu de traverser la table complète).

En outre, aucune autre suggestion d'index ne fonctionnerait car mysql s'arrêtera à reporting_date Condition de plage malheureusement . .

Pourquoi est-ce qu'il utilise temporaire?

car, vous utilisez groupe par - la requête va d'abord aller chercher toutes les données dans une table temporaire (également votre index ne couvre pas) et une fois ce processus effectué, il effectuera le Agrégation en conséquence.

Il est également expliqué dans la documentation MySQL :

Utilisation de temporaire (propriété JSON: utilisation_temporary_table)

Pour résoudre la requête, MySQL doit créer une table temporaire pour tenir le résultat. Cela se produit généralement si la requête contient du groupe par et Ordre par des clauses qui répertorient les colonnes différemment.


0 commentaires

0
votes

Pour cette requête:

select ck.*,
       (select sum(impressions)
        from keyword_report r2
        where r2.country = r.country and
              r2.keyword_id = r.keyword_id and
              r2.report_date = r.report_date
       ) as total_impressions
from (select distinct country, keyword_id
      from keyword_report r 
      where r.org_id = 1 and
            r.report_date = '2019-09-10' 
     ) ck;


1 commentaires

Gordon, Report_Date devrait être de la gamme. S'il vous plaît vérifier à nouveau.