Introducción al ajuste de escala automático de ranuras

Las reservas que configuras para usar el ajuste de escala automático de ranuras escalan automáticamente la capacidad asignada para satisfacer tus demandas de carga de trabajo. A medida que tu carga de trabajo aumenta o disminuye, BigQuery ajusta de forma dinámica tus ranuras a un nivel adecuado. Las reservas con ajuste de escala automático de ranuras solo están disponibles con las ediciones de BigQuery.

Usa las reservas de ajuste de escala automático

No es necesario que compres compromisos de ranuras antes de crear las reservas de ajuste de escala automático. Los compromisos de ranuras proporcionan una tarifa con descuento para las ranuras que se usan de forma coherente, pero son opcionales con reservas de ajuste de escala automático. Para crear una reserva de ajuste de escala automático, debes asignar a una reserva una cantidad máxima de ranuras (el tamaño máximo de la reserva). Para identificar la cantidad máxima de ranuras de ajuste de escala automático, resta el tamaño máximo de la reserva por cualquier ranura de referencia opcional asignada a la reserva.

Cuando crees reservas de ajuste de escala automático, ten en cuenta lo siguiente:

  • BigQuery escala las reservas por múltiplos de 100 hasta que haya alcanzado la cantidad de ranuras necesarias para ejecutar los trabajos o hasta alcanzar la cantidad máxima de ranuras disponibles para la reserva.
  • El escalamiento vertical se basa en una estimación y puede exceder o no aprovisionarse. Por ejemplo, el escalador automático puede escalar a 500 ranuras cuando solo se necesitan 400, o intenta escalar una cantidad pequeña cuando la carga de trabajo puede manejarse sin escalamiento.
  • Las ranuras con ajuste de escala automático se cobran según los precios de procesamiento de capacidad para la edición asociada mientras se escala verticalmente. Se te cobra por la cantidad de ranuras escaladas, no por la cantidad usada. Este cargo se aplica incluso si falla el trabajo que hace que BigQuery escale verticalmente.
  • Si bien la cantidad de ranuras siempre escala por múltiplos de 100, puede escalar más de 100 ranuras en un solo paso. Por ejemplo, si tu carga de trabajo requiere 450 ranuras adicionales, BigQuery puede intentar escalar en 500 ranuras a la vez para cumplir con el requisito de capacidad.
  • BigQuery reduce la escala cuando las ranuras asignadas superan la cantidad de ranuras necesarias y la capacidad de ajuste de escala automático permanece estable durante un tiempo.

Para aprender a trabajar con el ajuste de escala automático, consulta Trabaja con el ajuste de escala automático de ranuras.

Usa reservas con ranuras de referencia y ajuste de escala automático

Además de especificar el tamaño máximo de la reserva, puedes especificar de forma opcional una cantidad de referencia de ranuras por reserva. El modelo de referencia corresponde a la cantidad mínima de ranuras que se asignarán permanentemente a la reserva y siempre se te cobrará por ellas. Las ranuras con ajuste de escala automático solo se agregan después de que se consumen todas las ranuras del modelo de referencia (y las ranuras inactivas, si corresponde). Puedes compartir las ranuras del modelo de referencia inactivas en una reserva con otras reservas que necesiten capacidad.

Puedes aumentar la cantidad de ranuras del modelo de referencia en una reserva cada pocos minutos. Si deseas disminuir las ranuras del modelo de referencia, estarás limitado a una vez por hora si cambiaste recientemente la capacidad de la ranura del modelo de referencia y las ranuras del modelo de referencia superan las ranuras confirmadas. De lo contrario, puedes disminuir las ranuras del modelo de referencia cada pocos minutos.

Las ranuras del modelo de referencia y de ajuste de escala automático están diseñadas para proporcionar capacidad en función de tu carga de trabajo reciente. Si prevés que una carga de trabajo grande es muy diferente a las cargas de trabajo recientes, te recomendamos aumentar la capacidad del modelo de referencia antes del evento en lugar de depender de las ranuras de ajuste de escala automático para cubrir la capacidad de la carga de trabajo.

Si la reserva no tiene ranuras de referencia o no está configurada para tomar prestadas las ranuras inactivas de otras reservas, BigQuery intenta escalar. De lo contrario, las ranuras del modelo de referencia deben usarse por completo antes del escalamiento.

Las reservas usan y agregan ranuras con la siguiente prioridad:

  1. Ranuras del modelo de referencia.
  2. Uso compartido de ranuras inactivas (si está habilitado). Las reservas solo pueden compartir el modelo de referencia inactivo o las ranuras confirmadas de otras reservas que se crearon con la misma edición y la misma región.
  3. Ranuras con ajuste de escala automático.

En el siguiente ejemplo, las ranuras escalan desde un importe de referencia especificado. Las reservas etl y dashboard tienen un tamaño de referencia de 700 y 300 ranuras, respectivamente.

Ejemplo de ajuste de escala automático sin compromisos.

En este ejemplo, la reserva etl puede escalar a 1,300 ranuras (700 ranuras de modelo de referencia más 600 ranuras de ajuste de escala automático). Si la reserva dashboard noestá en uso, la reserva etl puede usar las 300 ranuras de la reserva dashboard si no se ejecuta ningún trabajo allí, lo que genera un máximo de 1,600 ranuras posibles.

La reserva dashboard puede escalar a 1,100 ranuras (300 ranuras de modelo de referencia más 800 ranuras de ajuste de escala automático). Si la reserva etl está completamente inactiva, la reserva dashboard puede escalar a un máximo de 1,800 ranuras (300 ranuras de modelo de referencia más 800 ranuras de ajuste de escala automático más 700 ranuras inactivas en la reserva etl).

Si la reserva etl requiere más de 700 ranuras de modelo de referencia, que siempre están disponibles, intenta agregar ranuras mediante los siguientes métodos en orden:

  1. 700 ranuras del modelo de referencia.
  2. Uso compartido de ranuras inactivas con las 300 ranuras de referencia en la reserva dashboard Tu reserva solo comparte las ranuras de modelo de referencia inactivas con otras reservas que se crean con la misma edición.
  3. Escala 600 ranuras adicionales hasta alcanzar el tamaño máximo de reserva.

Usa compromisos de ranuras

En el siguiente ejemplo, se muestra el ajuste de escala automático de ranuras mediante compromisos de capacidad.

Ejemplo de ajuste de escala automático

Al igual que los modelos de referencia de reserva, los compromisos de ranuras te permiten asignar una cantidad fija de ranuras que están disponibles para todas las reservas. A diferencia de las ranuras del modelo de referencia, un compromiso no se puede reducir durante el plazo. Los compromisos de ranuras son opcionales, pero pueden ahorrar costos si se requieren ranuras del modelo de referencia durante períodos prolongados.

En este ejemplo, se te cobra una tarifa predefinida por las ranuras del compromiso de capacidad. Se te cobra la tarifa de ajuste de escala automático por la cantidad de ranuras de ajuste de escala automático después de que se active el ajuste de escala automático y las reservas están en estado de ampliación. En el caso de la tarifa de ajuste de escala automático, se te cobra por la cantidad de ranuras escaladas, no por la cantidad usada.

Cantidad máxima de ranuras disponibles

Puedes calcular la cantidad máxima de ranuras que puede usar una reserva si agregas las ranuras de modelo de referencia, la cantidad máxima de ranuras para el ajuste de escala automático y cualquier ranura en los compromisos que se crearon con la misma edición y no están cubiertos por las ranuras de modelo de referencia. El ejemplo de la imagen anterior se configura de la siguiente manera:

  • Un compromiso de capacidad de 1,000 ranuras anuales. Esas ranuras se asignan como ranuras de referencia en las reservas etl y dashboard.
  • 700 ranuras de modelo de referencia asignadas a la reserva etl.
  • 300 ranuras de modelo de referencia asignadas a la reserva dashboard.
  • Ranuras de ajuste de escala automático de 600 para la reserva etl.
  • Ranuras de ajuste de escala automático de 800 para la reserva dashboard.

Para la reserva etl, la cantidad máxima de ranuras posible es igual a las ranuras del modelo de referencia etl (700) más las ranuras del modelo de referencia dashboard (300, si todas las ranuras están inactivas), más la cantidad máxima de ranuras con ajuste de escala automático (600). Por lo tanto, la cantidad máxima de ranuras que puede usar la reserva etl en este ejemplo es de 1,600. Esta cantidad excede la cantidad en el compromiso de capacidad.

En el siguiente ejemplo, el compromiso anual excede las ranuras de referencia asignadas.

Calcula las ranuras disponibles

En este ejemplo, tenemos lo siguiente:

  • Un compromiso de capacidad de 1,600 ranuras anuales.
  • Un tamaño máximo de reserva de 1,500 (incluidas 500 ranuras de ajuste de escala automático)
  • 1,000 ranuras de modelo de referencia asignadas a la reserva etl.

La cantidad máxima de ranuras disponibles para la reserva es igual a las ranuras del modelo de referencia (1,000) más cualquier ranura inactiva comprometida que no esté dedicada a las ranuras del modelo de referencia (1,600 ranuras anuales - 1,000 ranuras de referencia = 600) más la cantidad de ranuras con ajuste de escala automático (500) Por lo tanto, el máximo de ranuras posibles en esta reserva es 2,100. Las ranuras con ajuste de escala automático son ranuras adicionales por encima del compromiso de capacidad.

Prácticas recomendadas para el ajuste de escala automático

  1. Cuando uses el escalador automático por primera vez, configura la cantidad de ranuras de ajuste de escala automático en un número significativo en función del rendimiento pasado y esperado. Una vez creada la reserva, supervisa de forma activa la tasa de fallas, el rendimiento y la facturación, y ajusta la cantidad de ranuras de ajuste de escala automático según sea necesario.

  2. Ten en cuenta que se te cobrará por la cantidad de ranuras escaladas, no por la cantidad de ranuras que se usan. Si la cantidad máxima de ranuras de ajuste de escala automático es demasiado grande, BigQuery podría escalar más de lo necesario, lo que genera costos adicionales.

    Por ejemplo, un trabajo puede usar una gran cantidad de ranuras en un punto, pero solo necesita una cantidad significativamente menor. Debido a que BigQuery no libera las ranuras que no se usan de inmediato, esto puede reducir el uso si ningún otro trabajo en la reserva puede usar esas ranuras. Cuando se reduce el valor máximo para una reserva, se reduce la cantidad máxima de ranuras asignadas, lo que hace que el uso de ranuras del trabajo sea menos repentino y mejore el uso de trabajos de ranuras asignadas.

  3. En ocasiones, el uso de ranuras puede exceder la suma del modelo de referencia y las ranuras a gran escala. No se te cobrará por el uso de ranuras que sea mayor que tu modelo de referencia, más las ranuras escaladas.

  4. El escalador automático es más eficiente para cargas de trabajo pesadas y de larga duración, como las cargas de trabajo con varias consultas simultáneas. Evita enviar consultas de una en una al backend, ya sea que las consultas usen o no la caché. Sin ranuras de referencia, esto puede causar escalamiento inesperado y generar costos altos.

  5. El ajuste de escala automático de BigQuery está sujeto a disponibilidad de capacidad. BigQuery intenta satisfacer la demanda de capacidad del cliente según el uso histórico. Para lograr garantías de capacidad, puedes establecer un modelo de referencia de ranura opcional, que es la cantidad de ranuras garantizadas en una reserva. Con los modelos de referencia, las ranuras están disponibles de inmediato y pagas por ellas, sin importar si las usas o no. Si deseas garantizar que la capacidad esté disponible para las demandas inorgánicas grandes, como los días festivos de alto tráfico, comunícate con el equipo de BigQuery con varias semanas de anticipación.

  6. Las ranuras de referencia siempre se cobran. Si un compromiso de capacidad vence, es posible que debas ajustar de forma manual la cantidad de ranuras del modelo de referencia en tus reservas para evitar cargos no deseados. Por ejemplo, considera que tienes un compromiso de 1 año con 100 ranuras y una reserva con 100 ranuras de modelo de referencia. El compromiso vence y no tiene un plan de renovación. Una vez que venza el compromiso, pagarás por 100 ranuras de referencia en la tarifa de prepago.

Supervisa el ajuste de escala automático

Cuando supervisas el uso de ranuras con gráficos de recursos administrativos, es posible que veas ranuras mucho más escaladas que el uso de las ranuras, ya que los gráficos suavizan la cantidad de ranuras usadas durante el período de alineación. Para ver el uso de ranuras de ajuste de escala automático con detalles más precisos, reduce la opción de período. Esto actualiza automáticamente el período de alineación a un incremento menor.

En el siguiente ejemplo, el gráfico muestra ranuras mucho más escaladas que las que requiere la carga de trabajo.

El período de alineación se establece en un intervalo de un minuto y las ranuras escaladas aparecen más de lo que exige el uso de las ranuras.

Sin embargo, si acortas la opción de período para que el período de alineación sea de dos segundos, puedes ver que el escalador automático escala a la demanda de carga de trabajo y muestra datos más precisos. Para ajustar la opción del período, arrastra los rangos de inicio y finalización de la opción de período. Para mostrar los datos de demanda de carga de trabajo más precisos, selecciona p90 o p99 de la lista Métrica.

El período de alineación se establece en un intervalo de dos segundos, y las ranuras escaladas son adecuadas para la demanda de carga de trabajo.

Para obtener una vista más precisa del uso del ajuste de escala automático, usa un período de alineación de entre 1 y 15 segundos. Para obtener más información sobre el período de alineación de los gráficos de recursos administrativos, consulta Opción de períodos.

Para obtener información sobre cómo ver el uso de las ranuras, consulta Visualiza gráficos de recursos administrativos.

Supervisa el ajuste de escala automático con esquema de información

Puedes usar las siguientes secuencias de comandos SQL para verificar los segundos de ranuras facturados para una edición en particular. Debes ejecutar estas secuencias de comandos en el mismo proyecto en el que se crearon las reservas. La primera secuencia de comandos muestra los segundos de ranura facturados que cubre commitment_plan, mientras que la segunda secuencia de comandos muestra los segundos de ranura facturados que no están cubiertos por un compromiso.

Solo necesitas establecer el valor de tres variables para ejecutar estas secuencias de comandos:

  • start_time
  • end_time
  • edition_to_check

Estas secuencias de comandos están sujetas a las siguientes advertencias:

  • Las reservas y los compromisos de capacidad borrados se quitan de las vistas de esquema de información al final del período de retención de datos. Especifica un período reciente que no contenga las reservas y los compromisos borrados para los resultados correctos.

  • Es posible que el resultado de las secuencias de comandos no coincida exactamente con la factura debido a pequeños errores de redondeo.

La siguiente secuencia de comandos verifica el uso de ranuras que cubren los compromisos de una edición en particular.

Expande para ver la secuencia de comandos de las situaciones cubiertas

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

La siguiente secuencia de comandos verifica el uso de ranuras que no cubren los compromisos de una edición en particular. Este uso contiene dos tipos de ranuras, ranuras escaladas y ranuras de referencia que no están cubiertas por los compromisos.

Expande esta sección para ver la secuencia de comandos de las situaciones no cubiertas

/*
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

Cuotas

La suma del tamaño máximo de tu reserva no debe exceder la cuota de ranuras.

Para obtener información sobre las cuotas, consulta Cuotas y límites.

¿Qué sigue?