Présentation de l'autoscaling des emplacements

Les réservations que vous configurez pour utiliser l'autoscaling des emplacements effectuent un scaling automatique de la capacité allouée en fonction de vos charges de travail. À mesure que votre charge de travail augmente ou diminue, BigQuery ajuste dynamiquement vos emplacements au niveau approprié. Les réservations avec autoscaling des emplacements ne sont disponibles qu'avec les éditions BigQuery.

Utiliser les réservations d'autoscaling

Vous n'avez pas besoin de souscrire des engagements d'emplacements avant de créer des réservations d'autoscaling. Les engagements d'emplacements offrent un tarif réduit pour les emplacements utilisés de manière cohérente, mais sont facultatifs avec les réservations d'autoscaling. Pour créer une réservation d'autoscaling, vous attribuez à une réservation un nombre maximal d'emplacements (la taille maximale de la réservation). Vous pouvez identifier le nombre maximal d'emplacements d'autoscaling en soustrayant la taille de réservation maximale de tous les emplacements de référence facultatifs attribués à la réservation.

Lorsque vous créez des réservations d'autoscaling, tenez compte des points suivants :

  • BigQuery procède au scaling des réservations par multiples de 100 jusqu'à ce qu'il atteigne le nombre d'emplacements requis pour exécuter les jobs, ou le nombre d'emplacements disponibles pour la réservation.
  • Le scaling à la hausse est basé sur une estimation et peut entraîner un surprovisionnement ou un sous-provisionnement. Par exemple, l'autoscaler peut évoluer jusqu'à 500 emplacements lorsque seulement 400 emplacements sont nécessaires, ou essayer de réduire la capacité lorsque la charge de travail peut être traitée sans scaling.
  • Vos emplacements avec autoscaling sont facturés selon les tarifs des calculs de capacité de votre édition associée lors du scaling à la hausse. Vous êtes facturé pour le nombre d'emplacements avec scaling, et non pour le nombre d'emplacements utilisés. Ces frais s'appliquent même si la tâche qui entraîne le scaling à la hausse de BigQuery échoue.
  • Bien que le nombre d'emplacements évolue toujours par multiples de 100, le scaling peut ajouter plus de 100 emplacements en une seule fois. Par exemple, si votre charge de travail nécessite 450 emplacements supplémentaires, BigQuery peut tenter de procéder à un scaling à la hausse avec 500 emplacements en une seule fois pour répondre à la demande de capacité.
  • BigQuery procède à un scaling à la baisse lorsque les emplacements alloués dépassent le nombre d'emplacements requis, et quand la capacité d'autoscaling est stable depuis un certain temps.

Pour savoir comment utiliser l'autoscaling, consultez la section Utiliser l'autoscaling des emplacements.

Utiliser des réservations avec des emplacements de référence et d'autoscaling

En plus de spécifier la taille de réservation maximale, vous pouvez éventuellement spécifier un nombre de référence d'emplacements par réservation. Le nombre de référence correspond au nombre minimal d'emplacements qui seront toujours alloués à la réservation. Ces emplacements vous seront toujours facturés. Les emplacements d'autoscaling ne sont ajoutés qu'après la consommation de tous les emplacements de référence (et les emplacements inactifs, le cas échéant). Vous pouvez partager des emplacements de référence inactifs dans une réservation avec d'autres réservations nécessitant plus de capacité.

Vous pouvez augmenter le nombre d'emplacements de référence dans une réservation toutes les deux ou trois minutes. Si vous souhaitez réduire le nombre d'emplacements de référence, vous ne pouvez le faire qu'une fois par heure si vous avez récemment modifié votre capacité d'emplacements de référence et que vos emplacements de référence dépassent vos emplacements sur engagement. Autrement, vous pouvez réduire vos emplacements de référence toutes les deux ou trois minutes.

Les emplacements de référence et d'autoscaling sont destinés à fournir de la capacité en fonction de votre charge de travail récente. Si vous prévoyez une charge de travail importante très différente de vos charges de travail récentes, nous vous recommandons d'augmenter votre capacité de référence avant qu'elle ne survienne plutôt que de vous appuyer sur des emplacements d'autoscaling pour couvrir la capacité de charge de travail.

Si la réservation ne comporte pas d'emplacements de référence ou n'est pas configurée pour emprunter des emplacements inactifs à partir d'autres réservations, BigQuery tente d'effectuer le scaling. Autrement, les emplacements de référence doivent être pleinement utilisés avant le scaling.

Les réservations utilisent et ajoutent des emplacements dans l'ordre de priorité suivant :

  1. Nombre d'emplacements de base.
  2. Partage d'emplacements inactifs (si cette option est activée). Les réservations ne peuvent partager que des emplacements de référence inactifs ou des emplacements sur engagement d'autres réservations créées avec la même édition et la même région.
  3. Emplacements liés à l'autoscaling.

Dans l'exemple suivant, le nombre d'emplacements s'ajuste à partir d'une quantité de référence spécifiée. Les réservations etl et dashboard ont respectivement une taille de référence de 700 et 300 emplacements.

Exemple d'autoscaling sans aucun engagement.

Dans cet exemple, la réservation etl peut évoluer jusqu'à 1 300 emplacements (700 emplacements de référence et 600 emplacements liés à l'autoscaling). Si la réservation dashboard n'est pas utilisée, la réservation etl peut utiliser les 300 emplacements de la réservation dashboard si aucun job les concernant n'est en cours d'exécution, ce qui conduit à un maximum de 1 600 emplacements possibles.

La réservation dashboard peut évoluer jusqu'à 1 100 emplacements (300 emplacements de référence et 800 emplacements liés à l'autoscaling). Si la réservation etl est complètement inactive, la réservation dashboard peut évoluer jusqu'à un maximum de 1 800 emplacements (300 emplacements de référence, 800 emplacements liés à l'autoscaling et 700 emplacements inactifs dans la réservation etl).

Si la réservation etl nécessite plus de 700 emplacements de référence, qui sont toujours disponibles, elle tente d'ajouter des emplacements en utilisant les méthodes suivantes dans l'ordre :

  1. 700 emplacements de référence.
  2. Partage des emplacements inactifs avec les 300 emplacements de référence dans la réservation dashboard. Votre réservation ne partage que les emplacements de référence inactifs avec d'autres réservations créées avec la même édition.
  3. Scaling à la hausse de 600 emplacements supplémentaires jusqu'à la taille maximale de la réservation.

Utiliser des engagements d'emplacements

L'exemple suivant illustre l'autoscaling des emplacements à l'aide d'engagements de capacité.

Exemple d'autoscaling

À l'instar des valeurs de référence de réservation, les engagements d'emplacements vous permettent d'allouer un nombre fixe d'emplacements disponibles à toutes les réservations. Contrairement aux emplacements de référence, un engagement ne peut pas être réduit pendant la durée de l'engagement. Les engagements d'emplacements sont facultatifs mais peuvent réduire les coûts si des emplacements de référence sont requis pour de longues périodes.

Dans cet exemple, vous êtes facturé selon un tarif prédéfini pour les emplacements d'engagement de capacité. Vous êtes facturé au tarif de l'autoscaling pour le nombre d'emplacements d'autoscaling après l'activation de l'autoscaling et l'ajustement des réservations. Pour le taux d'autoscaling, le nombre d'emplacements mis à l'échelle vous est facturé, et non le nombre d'emplacements utilisés.

Nombre maximal d'emplacements disponibles

Vous pouvez calculer le nombre maximal d'emplacements qu'une réservation peut utiliser en additionnant les emplacements de référence, le nombre maximal d'emplacements avec autoscaling et tous les emplacements dans les engagements qui ont été créés avec la même édition et qui ne sont pas couverts par les emplacements de référence. L'exemple de l'image précédente est configuré comme suit :

  • Un engagement de capacité de 1 000 emplacements annuels. Ces emplacements sont attribués en tant qu'emplacements de référence dans la réservation etl et la réservation dashboard.
  • 700 emplacements de référence attribués à la réservation etl.
  • 300 emplacements de référence attribués à la réservation dashboard.
  • 600 emplacements liés à l'autoscaling pour la réservation etl.
  • 800 emplacements liés à l'autoscaling pour la réservation dashboard.

Pour la réservation etl, le nombre maximal d'emplacements possible est égal au nombre d'emplacements de référence etl (700), plus le nombre d'emplacements de référence dashboard (300, si tous les emplacements sont inactifs), plus le nombre maximal d'emplacements liés à l'autoscaling (600). Le nombre maximal d'emplacements que la réservation etl peut utiliser dans cet exemple est donc de 1 600. Ce nombre dépasse celui de l'engagement de capacité.

Dans l'exemple suivant, l'engagement annuel dépasse le nombre d'emplacements de référence attribués.

Calcul des emplacements disponibles

Dans cet exemple, nous avons :

  • Un engagement de capacité de 1 600 emplacements annuels.
  • Une taille de réservation maximale de 1 500 (y compris 500 emplacements d'autoscaling).
  • 1 000 emplacements de référence attribués à la réservation etl.

Le nombre maximal d'emplacements disponibles pour la réservation est égal au nombre d'emplacements de référence (1 000), plus tous les emplacements inactifs sur engagement qui ne sont pas dédiés aux emplacements de référence (1 600 emplacements annuels - 1 000 emplacements de référence = 600), plus le nombre d'emplacements d'autoscaling (500). Le nombre maximal d'emplacements potentiels dans cette réservation est donc de 2 100. Les emplacements avec autoscaling sont des emplacements supplémentaires qui dépassent l'engagement de capacité.

Bonnes pratiques en matière d'autoscaling

  1. Lorsque vous utilisez l'autoscaler pour la première fois, définissez le nombre d'emplacements d'autoscaling sur un nombre significatif en fonction des performances passées et attendues. Une fois la réservation créée, surveillez activement le taux d'échec, les performances et la facturation, puis ajustez le nombre d'emplacements d'autoscaling si nécessaire.

  2. Sachez que vous êtes facturé pour le nombre d'emplacements avec autoscaling, et non pour le nombre d'emplacements utilisés. Si le nombre maximal d'emplacements avec autoscaling est trop élevé, BigQuery peut effectuer plus de scaling que nécessaire, ce qui entraîne des coûts supplémentaires.

    Par exemple, une tâche peut utiliser un grand nombre d'emplacements à un moment donné, mais n'en avoir besoin que d'un nombre beaucoup plus faible. Étant donné que BigQuery ne libère pas immédiatement les emplacements inutilisés, cela peut réduire l'utilisation si aucune autre tâche de la réservation ne peut utiliser ces emplacements. En réduisant la valeur maximale d'une réservation, le nombre maximal d'emplacements alloués est réduit, ce qui réduit l'utilisation des emplacements de tâche et améliore l'utilisation des emplacements alloués.

  3. Le nombre d'emplacements utilisés peut parfois dépasser la somme de vos emplacements de base et de vos emplacements avec autoscaling. Les emplacements excédentaires (par rapport à la somme de vos emplacements de base et de vos emplacements avec autoscaling) ne vous sont pas facturés.

  4. L'autoscaler est plus efficace pour les charges de travail lourdes et de longue durée, telles que les charges de travail comportant plusieurs requêtes simultanées. Évitez d'envoyer des requêtes une par une au backend, que celles-ci utilisent ou non le cache. Sans emplacements de référence, cela peut entraîner un scaling inattendu et entraîner des coûts élevés.

  5. L'autoscaling BigQuery est soumis à une disponibilité de capacité. BigQuery tente de répondre à la demande de capacité des clients en fonction de l'historique d'utilisation. Pour obtenir des garanties de capacité, vous pouvez définir une base d'emplacements facultative, qui correspond au nombre d'emplacements garantis dans une réservation. Les références sont disponibles immédiatement et doivent être payées que vous les utilisiez ou non. Pour vous assurer de la capacité suffisante pour les demandes importantes et peu organiques (telles que les jours fériés), contactez l'équipe BigQuery plusieurs semaines à l'avance.

  6. Les emplacements de base sont toujours facturés. Si un engagement de capacité expire, vous devrez peut-être ajuster manuellement la quantité d'emplacements de base dans vos réservations afin d'éviter des frais inutiles. Par exemple, supposons que vous disposez d'un engagement d'un an avec 100 emplacements et une réservation avec 100 emplacements de base. L'engagement expire et n'offre pas d'option de renouvellement. Une fois l'engagement expiré, vous payez 100 emplacements de base au tarif à l'utilisation.

Surveiller l'autoscaling

Lorsque vous surveillez l'utilisation des emplacements avec des graphiques de ressources d'administration, vous pouvez constater une augmentation du nombre d'emplacements mis à l'échelle par rapport à votre utilisation d'emplacements, car les graphiques lissent le nombre d'emplacements utilisés pendant la période d'alignement. Pour afficher l'utilisation des emplacements avec autoscaling plus précisément, réduisez l'option de période. Cette action met automatiquement à jour la période d'alignement pour utiliser un incrément plus petit.

Dans l'exemple suivant, le graphique affiche un nombre d'emplacements mis à l'échelle bien plus important que la demande de la charge de travail.

La période d'alignement est définie sur un intervalle d'une minute et les emplacements mis à l'échelle apparaissent plus que les besoins d'utilisation d'emplacements.

Toutefois, si vous réduisez l'option de période afin que la période d'alignement soit de deux secondes, vous pouvez constater que l'autoscaler s'adapte à la demande de la charge de travail et affiche des données plus précises. Vous pouvez ajuster l'option de période en faisant glisser les plages de début et de fin de l'option de période. Pour afficher les données de demande de charge de travail les plus précises, sélectionnez p90 ou p99 dans la liste Métrique.

La période d'alignement est définie sur un intervalle de deux secondes et les emplacements mis à l'échelle sont adaptés à la demande de la charge de travail.

Pour obtenir une vue plus précise de l'utilisation de l'autoscaling, utilisez une période d'alignement comprise entre 1 et 15 secondes. Pour en savoir plus sur la période d'alignement des graphiques de ressources administratives, consultez la section Option de période.

Pour en savoir plus sur l'affichage de l'utilisation des emplacements, consultez la section Afficher les graphiques des ressources d'administration.

Surveiller l'autoscaling à l'aide d'un schéma d'informations

Vous pouvez utiliser les scripts SQL suivants pour vérifier les secondes d'utilisation des emplacements facturées pour une édition spécifique. Vous devez exécuter ces scripts dans le projet dans lequel les réservations ont été créées. Le premier script indique les secondes d'utilisation d'emplacements facturées qui sont couvertes par le plan commitment_plan, tandis que le second indique les secondes d'utilisation d'emplacements facturées qui ne sont pas couvertes par un engagement.

Il vous suffit de définir la valeur de trois variables pour exécuter ces scripts :

  • start_time
  • end_time
  • edition_to_check

Les mises en garde suivantes s'appliquent à ces scripts :

  • Les réservations et les engagements de capacité supprimés sont également supprimés des vues de schéma d'informations, à la fin de la période de conservation des données. Pour obtenir des résultats corrects, spécifiez une période récente ne contenant pas de réservations et d'engagements supprimés.

  • Le résultat des scripts peut ne pas correspondre exactement à la facture en raison de petites erreurs d'arrondi.

Le script suivant vérifie l'utilisation des emplacements qui est couverte par des engagements, pour une édition spécifique.

Développer pour afficher le script correspondant aux scénarios avec couverture par un engagement

DECLARE start_time,end_time TIMESTAMP;

DECLARE
  edition_to_check STRING;

/* Google uses Pacific Time to calculate the billing period for all customers,
regardless of their time zone. Use the following format if you want to match the
billing report. Change the start_time and end_time values to match the desired
window. */

/* The following three variables (start_time, end_time, and edition_to_check)
are the only variables that you need to set in the script.

During daylight savings time, the start_time and end_time variables should
follow this format: 2024-02-20 00:00:00-08. */

SET start_time = "2023-07-20 00:00:00-07";
SET end_time = "2023-07-28 00:00:00-07";
SET edition_to_check = 'ENTERPRISE';

/* The following function returns the slot seconds for the time window between
two capacity changes. For example, if there are 100 slots between (2023-06-01
10:00:00, 2023-06-01 11:00:00), then during that window the total slot seconds
will be 100 * 3600.

This script calculates a specific window (based on the variables defined above),
which is why the following script includes script_start_timestamp_unix_millis
and script_end_timestamp_unix_millis. */

CREATE TEMP FUNCTION
GetSlotSecondsBetweenChanges(
  slots FLOAT64,
  range_begin_timestamp_unix_millis FLOAT64,
  range_end_timestamp_unix_millis FLOAT64,
  script_start_timestamp_unix_millis FLOAT64,
  script_end_timestamp_unix_millis FLOAT64)
RETURNS INT64
LANGUAGE js
AS r"""
    if (script_end_timestamp_unix_millis < range_begin_timestamp_unix_millis || script_start_timestamp_unix_millis > range_end_timestamp_unix_millis) {
      return 0;
    }
    var begin = Math.max(script_start_timestamp_unix_millis, range_begin_timestamp_unix_millis)
    var end = Math.min(script_end_timestamp_unix_millis, range_end_timestamp_unix_millis)
    return slots * Math.ceil((end - begin) / 1000.0)
""";

/*
Sample CAPACITY_COMMITMENT_CHANGES data (unrelated columns ignored):
+---------------------+------------------------+-----------------+--------+------------+--------+
|  change_timestamp   | capacity_commitment_id | commitment_plan | state  | slot_count | action |
+---------------------+------------------------+-----------------+--------+------------+--------+
| 2023-07-20 19:30:27 | 12954109101902401697   | ANNUAL          | ACTIVE |        100 | CREATE |
| 2023-07-27 22:29:21 | 11445583810276646822   | FLEX            | ACTIVE |        100 | CREATE |
| 2023-07-27 23:10:06 | 7341455530498381779    | MONTHLY         | ACTIVE |        100 | CREATE |
| 2023-07-27 23:11:06 | 7341455530498381779    | FLEX            | ACTIVE |        100 | UPDATE |

The last row indicates a special change from MONTHLY to FLEX, which happens
because of commercial migration.

*/

WITH
  /*
  Information containing which commitment might have plan
  updated (e.g. renewal or commercial migration). For example:
  +------------------------+------------------+--------------------+--------+------------+--------+-----------+----------------------------+
  |  change_timestamp   | capacity_commitment_id | commitment_plan | state  | slot_count | action | next_plan | next_plan_change_timestamp |
  +---------------------+------------------------+-----------------+--------+------------+--------+-----------+----------------------------+
  | 2023-07-20 19:30:27 | 12954109101902401697   | ANNUAL          | ACTIVE |        100 | CREATE | ANNUAL    |        2023-07-20 19:30:27 |
  | 2023-07-27 22:29:21 | 11445583810276646822   | FLEX            | ACTIVE |        100 | CREATE | FLEX      |        2023-07-27 22:29:21 |
  | 2023-07-27 23:10:06 | 7341455530498381779    | MONTHLY         | ACTIVE |        100 | CREATE | FLEX      |        2023-07-27 23:11:06 |
  | 2023-07-27 23:11:06 | 7341455530498381779    | FLEX            | ACTIVE |        100 | UPDATE | FLEX      |        2023-07-27 23:11:06 |
  */
  commitments_with_next_plan AS (
    SELECT
      *,
      IFNULL(
        LEAD(commitment_plan)
          OVER (
            PARTITION BY capacity_commitment_id ORDER BY change_timestamp ASC
          ),
        commitment_plan)
        next_plan,
      IFNULL(
        LEAD(change_timestamp)
          OVER (
            PARTITION BY capacity_commitment_id ORDER BY change_timestamp ASC
          ),
        change_timestamp)
        next_plan_change_timestamp
    FROM
      `region-us.INFORMATION_SCHEMA.CAPACITY_COMMITMENT_CHANGES_BY_PROJECT`
  ),

  /*
  Insert a 'DELETE' action for those with updated plans. The FLEX commitment
  '7341455530498381779' is has no 'CREATE' action, and is instead labeled as an
  'UPDATE' action.

  For example:
  +---------------------+------------------------+-----------------+--------+------------+--------+
  |  change_timestamp   | capacity_commitment_id | commitment_plan | state  | slot_count | action |
  +---------------------+------------------------+-----------------+--------+------------+--------+
  | 2023-07-20 19:30:27 | 12954109101902401697   | ANNUAL          | ACTIVE |        100 | CREATE |
  | 2023-07-27 22:29:21 | 11445583810276646822   | FLEX            | ACTIVE |        100 | CREATE |
  | 2023-07-27 23:10:06 | 7341455530498381779    | MONTHLY         | ACTIVE |        100 | CREATE |
  | 2023-07-27 23:11:06 | 7341455530498381779    | FLEX            | ACTIVE |        100 | UPDATE |
  | 2023-07-27 23:11:06 | 7341455530498381779    | MONTHLY         | ACTIVE |        100 | DELETE |
  */

  capacity_changes_with_additional_deleted_event_for_changed_plan AS (
    SELECT
      next_plan_change_timestamp AS change_timestamp,
      project_id,
      project_number,
      capacity_commitment_id,
      commitment_plan,
      state,
      slot_count,
      'DELETE' AS action,
      commitment_start_time,
      commitment_end_time,
      failure_status,
      renewal_plan,
      user_email,
      edition,
      is_flat_rate,
    FROM commitments_with_next_plan
    WHERE commitment_plan <> next_plan
    UNION ALL
    SELECT * FROM `region-us.INFORMATION_SCHEMA.CAPACITY_COMMITMENT_CHANGES_BY_PROJECT`
  ),

  /*
  The committed_slots change the history. For example:
  +---------------------+------------------------+------------------+-----------------+
  |  change_timestamp   | capacity_commitment_id | slot_count_delta | commitment_plan |
  +---------------------+------------------------+------------------+-----------------+
  | 2023-07-20 19:30:27 | 12954109101902401697   |              100 | ANNUAL          |
  | 2023-07-27 22:29:21 | 11445583810276646822   |              100 | FLEX            |
  | 2023-07-27 23:10:06 | 7341455530498381779    |              100 | MONTHLY         |
  | 2023-07-27 23:11:06 | 7341455530498381779    |             -100 | MONTHLY         |
  | 2023-07-27 23:11:06 | 7341455530498381779    |              100 | FLEX            |
  */

  capacity_commitment_slot_data AS (
    SELECT
      change_timestamp,
      capacity_commitment_id,
      CASE
        WHEN action = "CREATE" OR action = "UPDATE"
          THEN
            IFNULL(
              IF(
                LAG(action)
                  OVER (
                    PARTITION BY capacity_commitment_id ORDER BY change_timestamp ASC, action ASC
                  )
                  IN UNNEST(['CREATE', 'UPDATE']),
                slot_count - LAG(slot_count)
                  OVER (
                    PARTITION BY capacity_commitment_id ORDER BY change_timestamp ASC, action ASC
                  ),
                slot_count),
              slot_count)
        ELSE
          IF(
            LAG(action)
              OVER (PARTITION BY capacity_commitment_id ORDER BY change_timestamp ASC, action ASC)
              IN UNNEST(['CREATE', 'UPDATE']),
            -1 * slot_count,
            0)
        END
        AS slot_count_delta,
      commitment_plan
    FROM
      capacity_changes_with_additional_deleted_event_for_changed_plan
    WHERE
      state = "ACTIVE"
      AND edition = edition_to_check
      AND change_timestamp <= end_time
  ),

  /*
  The total_committed_slots history for each plan. For example:
  +---------------------+---------------+-----------------+
  |  change_timestamp   | capacity_slot | commitment_plan |
  +---------------------+---------------+-----------------+
  | 2023-07-20 19:30:27 |           100 | ANNUAL          |
  | 2023-07-27 22:29:21 |           100 | FLEX            |
  | 2023-07-27 23:10:06 |           100 | MONTHLY         |
  | 2023-07-27 23:11:06 |             0 | MONTHLY         |
  | 2023-07-27 23:11:06 |           200 | FLEX            |
  */

  running_capacity_commitment_slot_data AS (
    SELECT
      change_timestamp,
      SUM(slot_count_delta)
        OVER (
          PARTITION BY commitment_plan
          ORDER BY change_timestamp
          RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
        )
        AS capacity_slot,
      commitment_plan,
    FROM
      capacity_commitment_slot_data
  ),

  /*

  The slot_seconds between each changes, partitioned by each plan. For example:
  +---------------------+--------------+-----------------+
  |  change_timestamp   | slot_seconds | commitment_plan |
  +---------------------+--------------+-----------------+
  | 2023-07-20 19:30:27 |     64617300 | ANNUAL          |
  | 2023-07-27 22:29:21 |       250500 | FLEX            |
  | 2023-07-27 23:10:06 |         6000 | MONTHLY         |
  | 2023-07-27 23:11:06 |            0 | MONTHLY         |
  | 2023-07-27 23:11:06 |      5626800 | FLEX            |
  */

  slot_seconds_data AS (
    SELECT
      change_timestamp,
      GetSlotSecondsBetweenChanges(
        capacity_slot,
        UNIX_MILLIS(change_timestamp),
        UNIX_MILLIS(
          IFNULL(
            LEAD(change_timestamp)
              OVER (PARTITION BY commitment_plan ORDER BY change_timestamp ASC),
            CURRENT_TIMESTAMP())),
        UNIX_MILLIS(start_time),
        UNIX_MILLIS(end_time)) AS slot_seconds,
      commitment_plan,
    FROM
      running_capacity_commitment_slot_data
    WHERE
      change_timestamp <= end_time
  )

/*

The final result is similar to the following:
+-----------------+--------------------+
| commitment_plan | total_slot_seconds |
+-----------------+--------------------+
| ANNUAL          |           64617300 |
| MONTHLY         |               6000 |
| FLEX            |            5877300 |
*/

SELECT
  commitment_plan,
  SUM(slot_seconds) AS total_slot_seconds
FROM
  slot_seconds_data
GROUP BY
  commitment_plan

Le script suivant vérifie l'utilisation des emplacements qui n'est couverte par aucun engagement, pour une édition spécifique. Cette utilisation englobe deux types d'emplacements : les emplacements soumis à autoscaling et les emplacements de base, qui ne sont couverts par aucun engagement.

Développer pour afficher le script correspondant aux scénarios sans couverture par un engagement

/*
This script has several parts:
1. Calculate the baseline and scaled slots for reservations
2. Calculate the committed slots
3. Join the two results above to calculate the baseline not covered by committed
   slots
4. Aggregate the number
*/

-- variables
DECLARE start_time, end_time TIMESTAMP;

DECLARE
  edition_to_check STRING;

/* Google uses Pacific Time to calculate the billing period for all customers,
regardless of their time zone. Use the following format if you want to match the
billing report. Change the start_time and end_time values to match the desired
window. */

/* The following three variables (start_time, end_time, and edition_to_check)
are the only variables that you need to set in the script.

During daylight savings time, the start_time and end_time variables should
follow this format: 2024-02-20 00:00:00-08. */

SET start_time = "2023-07-20 00:00:00-07";
SET end_time = "2023-07-28 00:00:00-07";
SET edition_to_check = 'ENTERPRISE';

/*
The following function returns the slot seconds for the time window between
two capacity changes. For example, if there are 100 slots between (2023-06-01
10:00:00, 2023-06-01 11:00:00), then during that window the total slot seconds
will be 100 * 3600.

This script calculates a specific window (based on the variables defined above),
which is why the following script includes script_start_timestamp_unix_millis
and script_end_timestamp_unix_millis. */

CREATE TEMP FUNCTION GetSlotSecondsBetweenChanges(
  slots FLOAT64,
  range_begin_timestamp_unix_millis FLOAT64,
  range_end_timestamp_unix_millis FLOAT64,
  script_start_timestamp_unix_millis FLOAT64,
  script_end_timestamp_unix_millis FLOAT64)
RETURNS INT64
LANGUAGE js
AS r"""
    if (script_end_timestamp_unix_millis < range_begin_timestamp_unix_millis || script_start_timestamp_unix_millis > range_end_timestamp_unix_millis) {
      return 0;
    }
    var begin = Math.max(script_start_timestamp_unix_millis, range_begin_timestamp_unix_millis)
    var end = Math.min(script_end_timestamp_unix_millis, range_end_timestamp_unix_millis)
    return slots * Math.ceil((end - begin) / 1000.0)
""";
/*
Sample RESERVATION_CHANGES data (unrelated columns ignored):
+---------------------+------------------+--------+---------------+---------------+
|  change_timestamp   | reservation_name | action | slot_capacity | current_slots |
+---------------------+------------------+--------+---------------+---------------+
| 2023-07-27 22:24:15 | res1             | CREATE |           300 |             0 |
| 2023-07-27 22:25:21 | res1             | UPDATE |           300 |           180 |
| 2023-07-27 22:39:14 | res1             | UPDATE |           300 |           100 |
| 2023-07-27 22:40:20 | res2             | CREATE |           300 |             0 |
| 2023-07-27 22:54:18 | res2             | UPDATE |           300 |           120 |
| 2023-07-27 22:55:23 | res1             | UPDATE |           300 |             0 |

Sample CAPACITY_COMMITMENT_CHANGES data (unrelated columns ignored):
+---------------------+------------------------+-----------------+--------+------------+--------+
|  change_timestamp   | capacity_commitment_id | commitment_plan | state  | slot_count | action |
+---------------------+------------------------+-----------------+--------+------------+--------+
| 2023-07-20 19:30:27 | 12954109101902401697   | ANNUAL          | ACTIVE |        100 | CREATE |
| 2023-07-27 22:29:21 | 11445583810276646822   | FLEX            | ACTIVE |        100 | CREATE |
| 2023-07-27 23:10:06 | 7341455530498381779    | MONTHLY         | ACTIVE |        100 | CREATE |
*/

WITH
  /*
  The scaled_slots & baseline change history:
  +---------------------+------------------+------------------------------+---------------------+
  |  change_timestamp   | reservation_name | autoscale_current_slot_delta | baseline_slot_delta |
  +---------------------+------------------+------------------------------+---------------------+
  | 2023-07-27 22:24:15 | res1             |                            0 |                 300 |
  | 2023-07-27 22:25:21 | res1             |                          180 |                   0 |
  | 2023-07-27 22:39:14 | res1             |                          -80 |                   0 |
  | 2023-07-27 22:40:20 | res2             |                            0 |                 300 |
  | 2023-07-27 22:54:18 | res2             |                          120 |                   0 |
  | 2023-07-27 22:55:23 | res1             |                         -100 |                   0 |
  */
  reservation_slot_data AS (
    SELECT
      change_timestamp,
      reservation_name,
      CASE action
        WHEN "CREATE" THEN autoscale.current_slots
        WHEN "UPDATE"
          THEN
            IFNULL(
              autoscale.current_slots - LAG(autoscale.current_slots)
                OVER (
                  PARTITION BY project_id, reservation_name
                  ORDER BY change_timestamp ASC, action ASC
                ),
              IFNULL(
                autoscale.current_slots,
                IFNULL(
                  -1 * LAG(autoscale.current_slots)
                    OVER (
                      PARTITION BY project_id, reservation_name
                      ORDER BY change_timestamp ASC, action ASC
                    ),
                  0)))
        WHEN "DELETE"
          THEN
            IF(
              LAG(action)
                OVER (
                  PARTITION BY project_id, reservation_name
                  ORDER BY change_timestamp ASC, action ASC
                )
                IN UNNEST(['CREATE', 'UPDATE']),
              -1 * autoscale.current_slots,
              0)
        END
        AS autoscale_current_slot_delta,
      CASE action
        WHEN "CREATE" THEN slot_capacity
        WHEN "UPDATE"
          THEN
            IFNULL(
              slot_capacity - LAG(slot_capacity)
                OVER (
                  PARTITION BY project_id, reservation_name
                  ORDER BY change_timestamp ASC, action ASC
                ),
              IFNULL(
                slot_capacity,
                IFNULL(
                  -1 * LAG(slot_capacity)
                    OVER (
                      PARTITION BY project_id, reservation_name
                      ORDER BY change_timestamp ASC, action ASC
                    ),
                  0)))
        WHEN "DELETE"
          THEN
            IF(
              LAG(action)
                OVER (
                  PARTITION BY project_id, reservation_name
                  ORDER BY change_timestamp ASC, action ASC
                )
                IN UNNEST(['CREATE', 'UPDATE']),
              -1 * slot_capacity,
              0)
        END
        AS baseline_slot_delta,
    FROM
      `region-us.INFORMATION_SCHEMA.RESERVATION_CHANGES`
    WHERE
      edition = edition_to_check
      AND change_timestamp <= end_time
  ),

  -- Convert the above to running total
  /*
  +---------------------+-------------------------+----------------+
  |  change_timestamp   | autoscale_current_slots | baseline_slots |
  +---------------------+-------------------------+----------------+
  | 2023-07-27 22:24:15 |                       0 |            300 |
  | 2023-07-27 22:25:21 |                     180 |            300 |
  | 2023-07-27 22:39:14 |                     100 |            300 |
  | 2023-07-27 22:40:20 |                     100 |            600 |
  | 2023-07-27 22:54:18 |                     220 |            600 |
  | 2023-07-27 22:55:23 |                     120 |            600 |
  */
  running_reservation_slot_data AS (
    SELECT
      change_timestamp,
      SUM(autoscale_current_slot_delta)
        OVER (ORDER BY change_timestamp RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
        AS autoscale_current_slots,
      SUM(baseline_slot_delta)
        OVER (ORDER BY change_timestamp RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
        AS baseline_slots,
    FROM
      reservation_slot_data
  ),

  /*
  The committed_slots change history. For example:
  +---------------------+------------------------+------------------+
  |  change_timestamp   | capacity_commitment_id | slot_count_delta |
  +---------------------+------------------------+------------------+
  | 2023-07-20 19:30:27 | 12954109101902401697   |              100 |
  | 2023-07-27 22:29:21 | 11445583810276646822   |              100 |
  | 2023-07-27 23:10:06 | 7341455530498381779    |              100 |
  */
  capacity_commitment_slot_data AS (
    SELECT
      change_timestamp,
      capacity_commitment_id,
      CASE
        WHEN action = "CREATE" OR action = "UPDATE"
          THEN
            IFNULL(
              IF(
                LAG(action)
                  OVER (
                    PARTITION BY capacity_commitment_id ORDER BY change_timestamp ASC, action ASC
                  )
                  IN UNNEST(['CREATE', 'UPDATE']),
                slot_count - LAG(slot_count)
                  OVER (
                    PARTITION BY capacity_commitment_id ORDER BY change_timestamp ASC, action ASC
                  ),
                slot_count),
              slot_count)
        ELSE
          IF(
            LAG(action)
              OVER (PARTITION BY capacity_commitment_id ORDER BY change_timestamp ASC, action ASC)
              IN UNNEST(['CREATE', 'UPDATE']),
            -1 * slot_count,
            0)
        END
        AS slot_count_delta
    FROM
      `region-us.INFORMATION_SCHEMA.CAPACITY_COMMITMENT_CHANGES_BY_PROJECT`
    WHERE
      state = "ACTIVE"
      AND edition = edition_to_check
      AND change_timestamp <= end_time
  ),

  /*
  The total_committed_slots history. For example:
  +---------------------+---------------+
  |  change_timestamp   | capacity_slot |
  +---------------------+---------------+
  | 2023-07-20 19:30:27 |           100 |
  | 2023-07-27 22:29:21 |           200 |
  | 2023-07-27 23:10:06 |           300 |
  */
  running_capacity_commitment_slot_data AS (
    SELECT
      change_timestamp,
      SUM(slot_count_delta)
        OVER (ORDER BY change_timestamp RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
        AS capacity_slot
    FROM
      capacity_commitment_slot_data
  ),

  /* Add next_change_timestamp to the above data,
   which will be used when joining with reservation data. For example:
  +---------------------+-----------------------+---------------+
  |  change_timestamp   | next_change_timestamp | capacity_slot |
  +---------------------+-----------------------+---------------+
  | 2023-07-20 19:30:27 |   2023-07-27 22:29:21 |           100 |
  | 2023-07-27 22:29:21 |   2023-07-27 23:10:06 |           200 |
  | 2023-07-27 23:10:06 |   2023-07-31 00:14:37 |           300 |
  */
  running_capacity_commitment_slot_data_with_next_change AS (
    SELECT
      change_timestamp,
      IFNULL(LEAD(change_timestamp) OVER (ORDER BY change_timestamp ASC), CURRENT_TIMESTAMP())
        AS next_change_timestamp,
      capacity_slot
    FROM
      running_capacity_commitment_slot_data
  ),

  /*
  Whenever we have a change in reservations or commitments,
  the scaled_slots_and_baseline_not_covered_by_commitments will be changed.
  Hence we get a collection of all the change_timestamp from both tables.
  +---------------------+
  |  change_timestamp   |
  +---------------------+
  | 2023-07-20 19:30:27 |
  | 2023-07-27 22:24:15 |
  | 2023-07-27 22:25:21 |
  | 2023-07-27 22:29:21 |
  | 2023-07-27 22:39:14 |
  | 2023-07-27 22:40:20 |
  | 2023-07-27 22:54:18 |
  | 2023-07-27 22:55:23 |
  | 2023-07-27 23:10:06 |
  */
  merged_timestamp AS (
    SELECT
      change_timestamp
    FROM
      running_reservation_slot_data
    UNION DISTINCT
    SELECT
      change_timestamp
    FROM
      running_capacity_commitment_slot_data
  ),

  /*
  Change running reservation-slots and make sure we have one row when commitment changes.
  +---------------------+-------------------------+----------------+
  |  change_timestamp   | autoscale_current_slots | baseline_slots |
  +---------------------+-------------------------+----------------+
  | 2023-07-20 19:30:27 |                       0 |              0 |
  | 2023-07-27 22:24:15 |                       0 |            300 |
  | 2023-07-27 22:25:21 |                     180 |            300 |
  | 2023-07-27 22:29:21 |                     180 |            300 |
  | 2023-07-27 22:39:14 |                     100 |            300 |
  | 2023-07-27 22:40:20 |                     100 |            600 |
  | 2023-07-27 22:54:18 |                     220 |            600 |
  | 2023-07-27 22:55:23 |                     120 |            600 |
  | 2023-07-27 23:10:06 |                     120 |            600 |
  */
  running_reservation_slot_data_with_merged_timestamp AS (
    SELECT
      change_timestamp,
      IFNULL(
        autoscale_current_slots,
        IFNULL(
          LAST_VALUE(autoscale_current_slots IGNORE NULLS) OVER (ORDER BY change_timestamp ASC), 0))
        AS autoscale_current_slots,
      IFNULL(
        baseline_slots,
        IFNULL(LAST_VALUE(baseline_slots IGNORE NULLS) OVER (ORDER BY change_timestamp ASC), 0))
        AS baseline_slots
    FROM
      running_reservation_slot_data
    RIGHT JOIN
      merged_timestamp
      USING (change_timestamp)
  ),

  /*
  Join the above, so that we will know the number for baseline not covered by commitments.
  +---------------------+-----------------------+-------------------------+------------------------------------+
  |  change_timestamp   | next_change_timestamp | autoscale_current_slots | baseline_not_covered_by_commitment |
  +---------------------+-----------------------+-------------------------+------------------------------------+
  | 2023-07-20 19:30:27 |   2023-07-27 22:24:15 |                       0 |                                  0 |
  | 2023-07-27 22:24:15 |   2023-07-27 22:25:21 |                       0 |                                200 |
  | 2023-07-27 22:25:21 |   2023-07-27 22:29:21 |                     180 |                                200 |
  | 2023-07-27 22:29:21 |   2023-07-27 22:39:14 |                     180 |                                100 |
  | 2023-07-27 22:39:14 |   2023-07-27 22:40:20 |                     100 |                                100 |
  | 2023-07-27 22:40:20 |   2023-07-27 22:54:18 |                     100 |                                400 |
  | 2023-07-27 22:54:18 |   2023-07-27 22:55:23 |                     220 |                                400 |
  | 2023-07-27 22:55:23 |   2023-07-27 23:10:06 |                     120 |                                400 |
  | 2023-07-27 23:10:06 |   2023-07-31 00:16:07 |                     120 |                                300 |
  */
  scaled_slots_and_baseline_not_covered_by_commitments AS (
    SELECT
      r.change_timestamp,
      IFNULL(LEAD(r.change_timestamp) OVER (ORDER BY r.change_timestamp ASC), CURRENT_TIMESTAMP())
        AS next_change_timestamp,
      r.autoscale_current_slots,
      IF(
        r.baseline_slots - IFNULL(c.capacity_slot, 0) > 0,
        r.baseline_slots - IFNULL(c.capacity_slot, 0),
        0) AS baseline_not_covered_by_commitment
    FROM
      running_reservation_slot_data_with_merged_timestamp r
    LEFT JOIN
      running_capacity_commitment_slot_data_with_next_change c
      ON
        r.change_timestamp >= c.change_timestamp
        AND r.change_timestamp < c.next_change_timestamp
  ),

  /*
  The slot_seconds between each changes. For example:
  +---------------------+--------------------+
  |  change_timestamp   | slot_seconds |
  +---------------------+--------------+
  | 2023-07-20 19:30:27 |            0 |
  | 2023-07-27 22:24:15 |        13400 |
  | 2023-07-27 22:25:21 |        91580 |
  | 2023-07-27 22:29:21 |       166320 |
  | 2023-07-27 22:39:14 |        13200 |
  | 2023-07-27 22:40:20 |       419500 |
  | 2023-07-27 22:54:18 |        40920 |
  | 2023-07-27 22:55:23 |       459160 |
  | 2023-07-27 23:10:06 |     11841480 |
  */
  slot_seconds_data AS (
    SELECT
      change_timestamp,
      GetSlotSecondsBetweenChanges(
        autoscale_current_slots + baseline_not_covered_by_commitment,
        UNIX_MILLIS(change_timestamp),
        UNIX_MILLIS(next_change_timestamp),
        UNIX_MILLIS(start_time),
        UNIX_MILLIS(end_time)) AS slot_seconds
    FROM
      scaled_slots_and_baseline_not_covered_by_commitments
    WHERE
      change_timestamp <= end_time AND next_change_timestamp > start_time
  )

/*
Final result for this example:
+--------------------+
| total_slot_seconds |
+--------------------+
|           13045560 |
*/
SELECT
  SUM(slot_seconds) AS total_slot_seconds
FROM
  slot_seconds_data

Quotas

La somme de votre taille de réservation maximale ne doit pas dépasser votre quota d'emplacements.

Pour en savoir plus sur les quotas, consultez la section Quotas et limites.

Étapes suivantes