Plan et chronologie de requête

Intégré aux tâches de requête, BigQuery inclut des informations de diagnostic sur le plan et la chronologie de la requête. Ces informations sont similaires à celles fournies par des instructions telles que EXPLAIN dans d'autres systèmes de bases de données et d'analyse. Ces informations peuvent être extraites des réponses d'API de méthodes telles que jobs.get.

BigQuery mettra régulièrement à jour ces statistiques pour les requêtes de longue durée. Ces mises à jour ont lieu indépendamment de la fréquence d'interrogation de l'état de la tâche. Elles sont généralement effectuées à des intervalles d'au moins 30 secondes. Par ailleurs, les tâches de requête qui ne tirent pas parti des ressources d'exécution, telles que les requêtes de simulation ou les résultats pouvant être diffusés à partir de résultats mis en cache, n'incluent pas les informations de diagnostic supplémentaires. Cependant, d'autres statistiques peuvent être présentes.

Contexte

Lorsque BigQuery exécute une tâche de requête, il convertit l'instruction SQL déclarative en un graphe d'exécution divisé en une série de phases de requête. Ces dernières sont composées d'ensembles d'étapes d'exécution plus précis. BigQuery exploite une architecture parallèle fortement distribuée pour exécuter ces requêtes, et les phases modélisent les unités de travail que de nombreux nœuds de calcul potentiels peuvent exécuter en parallèle. Les phases communiquent entre elles via une architecture de brassage distribuée rapide qui est présentée en détail sur cette page.

Dans le plan de requête, les termes "unités de travail" et "nœuds de calcul" sont utilisés, car le plan transmet des informations spécifiques sur le parallélisme. Ailleurs dans BigQuery, vous pouvez rencontrer le terme "emplacement" qui est une représentation abstraite des multiples attributs de l'exécution de requêtes, comme les ressources de calcul, de mémoire et d'E/S. Les statistiques d'une tâche de niveau supérieur fournissent une estimation du coût de la requête individuelle en utilisant l'estimation totalSlotMs de la requête à l'aide de cette comptabilité abstraite.

L'autre propriété importante qui caractérise l'architecture d'exécution d'une requête est sa nature dynamique. Cela signifie que le plan de requête peut être modifié lorsqu'une requête est en cours d'exécution. Les phases introduites lors de l'exécution d'une requête permettent souvent d'améliorer la distribution des données au sein des nœuds de calcul de la requête. Dans les plans de requête où c'est le cas, ceux-ci sont généralement libellés en tant que phases de répartition.

En plus du plan de requête, les tâches de requête présentent également une chronologie d'exécution, qui fournit le compte des unités de travail réalisées, en attente et actives au sein des nœuds de calcul de la requête. Une requête peut comporter simultanément plusieurs phases avec des nœuds de calcul actifs de sorte que la chronologie permet de montrer la progression globale de la requête.

Afficher des informations avec l'UI Web de BigQuery

Si vous utilisez l'UI Web de BigQuery, vous pouvez afficher les informations du plan de requête correspondant à une requête terminée en cliquant sur le bouton Détails (à droite du bouton Résultats).

Capture d'écran du plan de requête

Pour les requêtes de longue durée, vous pouvez afficher le plan de requête au fur et à mesure de sa progression en cliquant sur le lien situé dans la ligne d'état de la requête sous le volet de rédaction de la requête.

Capture d'écran de la ligne d'état du temps écoulé

Informations sur le plan de requête

Dans la réponse de l'API, les plans de requête sont représentés sous la forme d'une liste de phases de requête qui présente les statistiques d'aperçu par phase, les informations des étapes détaillées et les classifications chronologiques des phases. Toutes les informations ne figurent pas dans l'UI Web, mais elles sont toutes disponibles dans les réponses de l'API.

Aperçu de la phase

Les champs d'aperçu correspondant à chaque phase peuvent inclure les éléments suivants :

Champ de l'API Description
id ID numérique unique de la phase.
name Nom simple résumant la phase. Les steps constituant la phase fournissent des informations supplémentaires sur les étapes d'exécution.
status État d'exécution de la phase. Les états possibles incluent PENDING (EN ATTENTE), RUNNING (EN COURS D'EXÉCUTION), COMPLETE (TERMINÉE), FAILED (ÉCHOUÉE) et CANCELLED (ANNULÉE).
inputStages Liste des ID qui forment le graphe de dépendance de la phase. Par exemple, une phase JOIN (jointure) nécessite souvent deux phases dépendantes qui préparent les données à gauche et à droite de la relation JOIN.
startMs Horodatage en millisecondes d'itération qui représente le début de l'exécution du premier nœud de calcul au sein de la phase.
endMs Horodatage en millisecondes d'itération qui représente la fin de l'exécution du dernier nœud de calcul.
steps Liste plus détaillée des étapes d'exécution qui constituent la phase. Consultez la section suivante pour plus d'informations.
recordsRead Taille d'entrée de la phase sous forme de nombre d'enregistrements pour tous les nœuds de calcul de la phase.
recordsWritten Taille de sortie de la phase sous forme de nombre d'enregistrements pour tous les nœuds de calcul de la phase.
parallelInputs Nombre d'unités de travail chargeables en parallèle pour la phase. Selon la phase et la requête, cela peut représenter le nombre de segments de colonne dans une table ou le nombre de partitions dans un brassage intermédiaire.
completedParallelInputs Nombre d'unités de travail de la phase qui ont été achevées. Pour certaines requêtes, il n'est pas nécessaire que toutes les entrées d'une phase soient achevées pour que la phase se termine.
shuffleOutputBytes Représente le nombre total d'octets écrits pour tous les nœuds de calcul au sein d'une phase de requête.
shuffleOutputBytesSpilled Les requêtes qui transmettent des données importantes entre les phases peuvent nécessiter un retour vers une transmission sur disque. La statistique d'octets répandus indique la quantité de données répandues sur le disque.

Informations sur les étapes par phase

Les étapes représentent les opérations plus précises que chaque nœud de calcul d'une phase doit exécuter. Elles sont présentées sous la forme d'une liste numérotée d'opérations. Les étapes sont classées par catégories, et certaines opérations fournissent des informations plus détaillées. Les catégories d'opérations présentes dans le plan de requête sont les suivantes :

Étape Description
READ Lecture d'une ou plusieurs colonnes d'une table d'entrée ou d'un mélange intermédiaire.
WRITE Écriture d'une ou plusieurs colonnes dans une table de sortie ou un résultat intermédiaire. Pour les sorties d'une phase partitionnées en hachage, cela inclut également les colonnes servant de clé de partition.
COMPUTE Opérations telles que l'évaluation des expressions et les fonctions SQL.
FILTER Opérateur mettant en œuvre les clauses WHERE, OMIT IF et HAVING.
SORT Opération "Trier" ou "Trier par", qui inclut les touches de colonne et la direction.
AGGREGATE Opération d'agrégation, telle que GROUPER PAR ou COMPTER.
LIMIT Opérateur mettant en œuvre la clause LIMIT.
JOIN Opération JOIN qui inclut le type de jointure et les colonnes utilisées.
ANALYTIC_FUNCTION Invocation d'une fonction analytique (également appelée "fenêtrage").
USER_DEFINED_FUNCTION Appel d'une fonction définie par l'utilisateur.

Classification des durées par phase

Les phases de requête fournissent également des classifications de durées des phases, sous forme relative et absolue. Chaque phase d'exécution représentant un travail effectué par un ou plusieurs nœuds de calcul indépendants, les informations sont fournies en termes de durée moyenne et de durée maximale. Ces durées représentent respectivement la performance moyenne de tous les nœuds de calcul d'une phase et la performance la plus lente des nœuds de calcul pour une classification donnée. Les durées moyennes et maximales sont en outre divisées en représentations absolues et relatives. Pour les statistiques basées sur les ratios, les données sont fournies sous forme de fraction de la durée la plus longue passée par un nœud de calcul dans un segment quelconque.

L'UI Web présente la durée des phases à l'aide de représentations temporelles relatives.

Les informations relatives à la durée des phases sont présentées comme suit :

Durée relative Durée absolue UI Web* Numérateur de taux **
waitRatioAvg waitMsAvg Barre jaune foncé waitRatioAvg Temps passé par le nœud de calcul moyen à attendre d'être planifié.
waitRatioMax waitMsMax Barre jaune waitRatioMax Temps passé par le nœud de calcul le plus lent à attendre d'être planifié.
readRatioAvg readMsAvg Barre violet foncé readRatioAvg Temps passé par le nœud de calcul moyen à lire les données d'entrée.
readRatioMax readMsMax Barre violette readRatioMax Temps passé par le nœud de calcul le plus lent à lire les données d'entrée.
computeRatioAvg computeMsAvg Barre orange foncé computeRatioAvg Temps passé par le nœud de calcul moyen à être lié au processeur.
computeRatioMax computeMsMax Barre orange computeRatioMax Temps passé par le nœud de calcul le plus lent à être lié au processeur.
writeRatioAvg writeMsAvg Barre bleu foncé writeRatioAvg Temps passé par le nœud de calcul moyen à écrire les données de sortie.
writeRatioMax writeMsMax Barre bleue writeRatioMax Temps passé par le nœud de calcul le plus lent à écrire les données de sortie.

* Les libellés "AVG" et "MAX" sont fournis à titre d'exemple uniquement et ne figurent pas dans l'UI Web.

Métadonnées de chronologie

La chronologie de la requête indique les progrès réalisés à des moments précis et fournit des aperçus instantanés de la progression globale de la requête. La chronologie est représentée par une série d'échantillons qui indiquent les informations suivantes :

Champ Description
elapsedMs Millisecondes écoulées depuis le début de l'exécution de la requête.
totalSlotMs Représentation cumulée des intervalles de millisecondes utilisés par la requête.
pendingUnits Nombre total d'unités de travail planifiées et en attente d'exécution.
activeUnits Nombre total d'unités de travail actives en cours de traitement par les nœuds de calcul.
completedUnits Nombre total d'unités de travail effectuées lors de l'exécution de cette requête.

Exemple de requête

Si vous exécutez une requête simple qui compte le nombre de lignes de l'ensemble de données public Shakespeare et effectue un deuxième compte conditionnel qui limite les résultats aux lignes qui font référence à hamlet :

#StandardSQL
SELECT
  COUNT(1) as rowcount,
  COUNTIF(corpus = 'hamlet') as rowcount_hamlet
FROM `publicdata.samples.shakespeare`

Cliquez sur Détails pour afficher les informations suivantes sur le plan de requête. Examinons la première section qui contient la chronologie de la requête :

Capture d'écran de la chronologie de la requête hamlet

Cet exemple présente une très petite table d'échantillons et une requête simple. Il ne compte donc que deux unités de travail au total. Dans cet exemple, tout le travail est terminé presque immédiatement.

Nous allons voir plus bas et examiner le plan de requête :

Capture d'écran du plan de la requête hamlet

Dans cet exemple, les indicateurs de couleur affichent les temps relatifs correspondant à toutes les phases. À partir des informations d'entrée parallèles, nous constatons que chaque phase ne nécessite qu'un seul nœud de calcul. Il n'y a donc pas d'écart entre les temps moyens et les temps les plus longs.

Nous pouvons également remarquer que, pour cette requête triviale, le temps le plus long de n'importe quel segment correspond au temps passé par un seul nœud de calcul de la phase 01 à attendre que la phase 00 se termine. Cela est dû au fait que la phase 01 est dépendante de l'entrée de la phase 00 et n'a pas pu démarrer tant que la première phase n'avait pas écrit sa sortie (une ligne, environ 18 octets) en brassage intermédiaire.

Examinons maintenant plus en détail les étapes de nos phases d'exécution. À gauche du libellé de la phase, cliquez sur le triangle pour développer les informations de la phase :

Capture d'écran des détails des étapes du plan de la requête hamlet

Dans ce cas, nous pouvons voir le plan d'exécution correspondant au nœud de calcul unique qui a effectué le travail de la phase 00. Tout d'abord, les données ont été lues (READ) depuis la colonne "corpus" de la table shakespeare référencée. Ensuite, des agrégations (AGGREGATE) ont été établies pour les projections COUNT et COUNTIF. L'analyse des données a nécessité une étape COMPUTE, qui a fourni des données pour les comptes normaux et conditionnels, et la sortie a été écrite sur la sortie de brassage intermédiaire, appelée __stage00_output dans ce plan.

Création de rapports d'erreurs

Il est possible que les tâches de requête échouent en cours d'exécution. Les informations du plan étant régulièrement mises à jour, vous pouvez observer où l'échec a eu lieu sur le graphe d'exécution. Dans l'UI, les phases réussies et échouées sont identifiées par une coche et un point d'exclamation situés à côté du ou des noms de la phase.

Pour plus d'informations sur l'interprétation et la résolution des erreurs, consultez le guide de dépannage.

Exemple de représentation de l'API

Les informations du plan de requête sont automatiquement intégrées dans les informations de réponse de la tâche sans avoir à appeler de méthodes supplémentaires. Elles peuvent être extraites simplement en appelant jobs.get pour récupérer les informations de la tâche. L'exemple suivant est un extrait d'une réponse JSON pour une tâche affichant l'exemple de requête hamlet. Il indique à la fois les informations du plan et de la chronologie de la requête.

"statistics": {
  "query": {
    "cacheHit": false,
    "queryPlan": [
      {
        "completedParallelInputs": "1",
        "computeMsAvg": "25",
        "computeMsMax": "25",
        "computeRatioAvg": 0.17857142857142858,
        "computeRatioMax": 0.17857142857142858,
        "endMs": "1522787349945",
        "id": "0",
        "name": "S00: Input",
        "parallelInputs": "1",
        "readMsAvg": "28",
        "readMsMax": "28",
        "readRatioAvg": 0.2,
        "readRatioMax": 0.2,
        "recordsRead": "164656",
        "recordsWritten": "1",
        "shuffleOutputBytes": "18",
        "shuffleOutputBytesSpilled": "0",
        "startMs": "1522787349898",
        "status": "COMPLETE",
        "steps": [
          {
            "kind": "READ",
            "substeps": [
              "$1:corpus",
              "FROM publicdata.samples.shakespeare"
            ]
          },
          {
            "kind": "AGGREGATE",
            "substeps": [
              "$20 := COUNT($30)",
              "$21 := COUNTIF($31)"
            ]
          },
          {
            "kind": "COMPUTE",
            "substeps": [
              "$30 := 1",
              "$31 := equal($1, 'hamlet')"
            ]
          },
          {
            "kind": "WRITE",
            "substeps": [
              "$20, $21",
              "TO __stage00_output"
            ]
          }
        ],
        "waitMsAvg": "0",
        "waitMsMax": "0",
        "waitRatioAvg": 0.0,
        "waitRatioMax": 0.0,
        "writeMsAvg": "5",
        "writeMsMax": "5",
        "writeRatioAvg": 0.03571428571428571,
        "writeRatioMax": 0.03571428571428571
      },
      {
        "completedParallelInputs": "1",
        "computeMsAvg": "14",
        "computeMsMax": "14",
        "computeRatioAvg": 0.1,
        "computeRatioMax": 0.1,
        "endMs": "1522787350180",
        "id": "1",
        "inputStages": [
          "0"
        ],
        "name": "S01: Output",
        "parallelInputs": "1",
        "readMsAvg": "0",
        "readMsMax": "0",
        "readRatioAvg": 0.0,
        "readRatioMax": 0.0,
        "recordsRead": "1",
        "recordsWritten": "1",
        "shuffleOutputBytes": "16",
        "shuffleOutputBytesSpilled": "0",
        "startMs": "1522787350038",
        "status": "COMPLETE",
        "steps": [
          {
            "kind": "READ",
            "substeps": [
              "$20, $21",
              "FROM __stage00_output"
            ]
          },
          {
            "kind": "AGGREGATE",
            "substeps": [
              "$10 := SUM_OF_COUNTS($20)",
              "$11 := SUM_OF_COUNTS($21)"
            ]
          },
          {
            "kind": "WRITE",
            "substeps": [
              "$10, $11",
              "TO __stage01_output"
            ]
          }
        ],
        "waitMsAvg": "140",
        "waitMsMax": "140",
        "waitRatioAvg": 1.0,
        "waitRatioMax": 1.0,
        "writeMsAvg": "129",
        "writeMsMax": "129",
        "writeRatioAvg": 0.9214285714285714,
        "writeRatioMax": 0.9214285714285714
      }
    ],
    "referencedTables": [
      {
        "datasetId": "samples",
        "projectId": "publicdata",
        "tableId": "shakespeare"
      }
    ],
    "statementType": "SELECT",
    "timeline": [
      {
        "activeUnits": "0",
        "completedUnits": "2",
        "elapsedMs": "999",
        "pendingUnits": "0",
        "totalSlotMs": "185"
      },
      {
        "activeUnits": "0",
        "completedUnits": "2",
        "elapsedMs": "1197",
        "pendingUnits": "0",
        "totalSlotMs": "185"
      }
    ],
    "totalBytesBilled": "10485760",
    "totalBytesProcessed": "2464625",
    "totalPartitionsProcessed": "0",
    "totalSlotMs": "127"
  },
  "totalBytesProcessed": "2464625"
},

Utiliser les informations d'exécution

Les plans de requête BigQuery fournissent des informations sur la manière dont le service exécute les requêtes, mais la gestion du service limite l'exploitation directe de certaines informations. De nombreuses optimisations se produisent automatiquement en utilisant simplement le service, qui peut être différent des autres environnements où les réglages, le provisionnement et la surveillance peuvent nécessiter du personnel dédié et compétent.

Pour connaître les techniques spécifiques susceptibles d'améliorer l'exécution et les performances des requêtes, consultez la documentation sur les bonnes pratiques. Les statistiques du plan et de la chronologie de requête peuvent vous aider à savoir si certaines phases utilisent davantage de ressources. Par exemple, une phase JOIN qui génère beaucoup plus de lignes de sortie que de lignes d'entrée peut indiquer la possibilité de filtrer plus tôt dans la requête.

En outre, les informations de chronologie peuvent permettre de savoir si une requête donnée est lente par elle-même ou à cause des effets d'autres requêtes en concurrence pour les mêmes ressources. Si vous constatez que le nombre d'unités actives reste limité tout au long de la requête, mais que la quantité d'unités de travail en file d'attente reste élevée, il peut s'agir de cas où la réduction du nombre de requêtes simultanées pourrait améliorer significativement la durée d'exécution globale de certaines requêtes.

Cette page vous a-t-elle été utile ? Évaluez-la :

Envoyer des commentaires concernant…

Besoin d'aide ? Consultez notre page d'assistance.