Introducción al autoescalado de ranuras

Las reservas que configures para usar el autoescalado de ranuras escalan automáticamente la capacidad asignada para adaptarse a las demandas de tu carga de trabajo. A medida que tu carga de trabajo aumenta o disminuye, BigQuery ajusta dinámicamente tus slots a un nivel adecuado. Las reservas con autoescalado de ranuras solo están disponibles en las ediciones de BigQuery.

Usar reservas de ajuste automático de escala

No es necesario que compres compromisos de espacio antes de crear reservas con escalado automático. Los compromisos de espacio proporcionan una tarifa con descuento para los espacios que se usan de forma constante, pero son opcionales con las reservas de escalado automático. Para crear una reserva de escalado automático, asigna a la reserva un número máximo de ranuras (el tamaño máximo de la reserva). Para identificar el número máximo de espacios de autoescalado, resta el tamaño máximo de la reserva a los espacios de referencia opcionales asignados a la reserva.

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

  • BigQuery escala las reservas casi al instante hasta que alcanza el número de ranuras necesarias para ejecutar las tareas o hasta que llega al número máximo de ranuras disponibles para la reserva. Los espacios publicitarios siempre se escalan automáticamente a un múltiplo de 50.
  • El aumento de recursos se basa en el uso real y se redondea al incremento de 50 ranuras más cercano.
  • Las ranuras con escalado automático se cobran según los precios de computación de capacidad de la edición asociada mientras se escalan. Se te cobra por el número de ranuras escaladas, no por el número de ranuras utilizadas. Este cargo se aplica aunque falle la tarea que provoca que BigQuery aumente la capacidad. Por este motivo, no utilices el esquema de información de trabajos para que coincida con la facturación. En su lugar, consulta Monitorizar el escalado automático con el esquema de información.
  • Aunque el número de ranuras siempre se escala en múltiplos de 50, puede aumentar en más de 50 ranuras en un solo paso. Por ejemplo, si tu carga de trabajo requiere 450 ranuras adicionales, BigQuery puede intentar escalar en 450 ranuras a la vez para cumplir el requisito de capacidad.
  • BigQuery reduce la escala cuando las tareas asociadas a la reserva ya no necesitan la capacidad (con un mínimo de 1 minuto).

La capacidad escalada automáticamente se conserva durante al menos 60 segundos. Este periodo de 60 segundos se denomina "ventana de reducción". Cualquier nuevo pico de capacidad restablece el periodo de reducción, y trata todo el nivel de capacidad como una nueva concesión. Sin embargo, si han pasado 60 segundos o más desde el último aumento de capacidad y hay menos demanda, el sistema reduce la capacidad sin restablecer el periodo de reducción, lo que permite que se produzcan disminuciones consecutivas sin que se imponga un retraso.

Por ejemplo, si la capacidad inicial de tu carga de trabajo se escala a 100 ranuras, el pico se mantendrá durante al menos 60 segundos. Si, durante ese periodo de reducción, tu carga de trabajo se amplía hasta un nuevo pico de 200 ranuras, se iniciará un nuevo periodo de reducción de 60 segundos. Si no hay ningún nuevo pico durante este periodo de reducción, tu carga de trabajo empezará a reducirse al final de los 60 segundos.

Veamos un ejemplo detallado: a las 12:00:00, tu capacidad inicial se amplía a 100 espacios y el uso dura un segundo. Ese pico se mantiene durante al menos 60 segundos, a partir de las 12:00:00. Una vez transcurridos los 60 segundos (a las 12:01:01), si el nuevo uso es de 50 ranuras, BigQuery se reducirá a 50 ranuras. Si, a las 12:01:02, el nuevo uso es de 0 ranuras, BigQuery vuelve a reducir la escala inmediatamente a 0 ranuras. Una vez que haya finalizado el periodo de reducción, BigQuery puede reducir el tamaño varias veces consecutivas sin necesidad de que se abra un nuevo periodo.

Para saber cómo usar el autoescalado, consulta Trabajar con el autoescalado de ranuras.

Usar reservas con slots de referencia y de autoescalado

Además de especificar el tamaño máximo de la reserva, puedes especificar de forma opcional un número de referencia de espacios por reserva. La base es el número mínimo de espacios que siempre se asignarán a la reserva y por los que siempre se te cobrará. Los espacios de autoescalado solo se añaden después de que se hayan consumido todos los espacios de referencia (y los espacios inactivos, si procede). Puedes compartir las ranuras de referencia inactivas de una reserva con otras reservas que necesiten capacidad.

Puedes aumentar el número de espacios publicitarios de referencia de una reserva cada pocos minutos. Si quieres reducir tus espacios publicitarios de referencia, solo podrás hacerlo una vez por hora si has cambiado recientemente la capacidad de tus espacios publicitarios de referencia y estos superan a los espacios publicitarios comprometidos. De lo contrario, puedes reducir los espacios publicitarios básicos cada pocos minutos.

Las ranuras de referencia y de autoescalado están diseñadas para proporcionar capacidad en función de tu carga de trabajo reciente. Si prevés una carga de trabajo grande que sea muy diferente de tus cargas de trabajo recientes, te recomendamos que aumentes tu capacidad de base antes del evento en lugar de depender de las ranuras de escalado automático para cubrir la capacidad de la carga de trabajo. Si tienes problemas para aumentar tu capacidad base, vuelve a intentar la solicitud después de esperar 15 minutos.

Si la reserva no tiene ranuras de base o no está configurada para tomar prestadas ranuras inactivas de otras reservas, BigQuery intentará escalar. De lo contrario, las franjas de referencia deben utilizarse por completo antes de escalar.

Las reservas usan y añaden espacios con la siguiente prioridad:

  1. Espacios de referencia.
  2. Compartir espacios inactivos (si está habilitado). Las reservas solo pueden compartir ranuras de referencia inactivas o comprometidas de otras reservas que se hayan creado con la misma edición y la misma región.
  3. Ranuras de autoescalado.

En el siguiente ejemplo, los espacios se escalan a partir de una cantidad de referencia especificada. Las reservas de etl y dashboard tienen un tamaño base de 700 y 300 espacios, respectivamente.

Ejemplo de autoescalado sin compromisos.

En este ejemplo, la reserva etl puede ampliarse a 1300 ranuras (700 ranuras de referencia más 600 ranuras de escalado automático). Si la reserva dashboard no se está usando, la reserva etl puede usar las 300 ranuras de la reserva dashboard si no se está ejecutando ninguna tarea en ella, lo que da como resultado un máximo de 1600 ranuras posibles.

La dashboard reserva puede escalarse hasta 1100 espacios (300 espacios de referencia más 800 espacios de autoescalado). Si la reserva etl está totalmente inactiva, la reserva dashboard puede escalar hasta un máximo de 1800 espacios (300 espacios de referencia más 800 espacios de escalado automático más 700 espacios inactivos en la reserva etl).

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

  1. 700 espacios publicitarios de referencia.
  2. Compartir slots inactivos con los 300 slots de referencia de la reserva dashboard. Tu reserva solo comparte las ranuras de línea base inactivas con otras reservas creadas con la misma edición.
  3. Aumentar el número de espacios en 600 hasta alcanzar el tamaño máximo de reserva.

Usar confirmaciones de ranuras

En el siguiente ejemplo se muestra el escalado automático de ranuras mediante compromisos de capacidad.

Ejemplo de autoescalado

Al igual que las bases de referencia de las reservas, los compromisos de espacio te permiten asignar un número fijo de espacios que están disponibles para todas las reservas. A diferencia de las franjas de referencia, el compromiso no se puede reducir durante el plazo. Los compromisos de ranuras son opcionales, pero pueden ahorrar costes si se necesitan ranuras de referencia durante largos periodos.

En este ejemplo, se te cobra una tarifa predefinida por las ranuras de compromiso de capacidad. Se te cobra la tarifa de autoescalado por el número de ranuras de autoescalado después de que se active el autoescalado y las reservas estén en un estado de escalado. En el caso de la tarifa de autoescalado, se te cobra por el número de ranuras escaladas, no por el número de ranuras utilizadas.

En el siguiente ejemplo se muestran las reservas cuando el número de espacios de referencia supera el número de espacios comprometidos.

Las ranuras de referencia superan el número de ranuras comprometidas.

En este ejemplo, hay un total de 1000 ranuras de referencia entre las dos reservas: 500 de la reserva etl y 500 de la reserva dashboard. Sin embargo, el compromiso solo cubre 800 espacios. En este caso, los espacios adicionales se cobran según la tarifa de pago por uso.

Número máximo de ranuras disponibles

Para calcular el número máximo de espacios que puede usar una reserva, suma los espacios de referencia, el número máximo de espacios de escalado automático y los espacios de los compromisos que se hayan creado con la misma edición y que no estén incluidos en los espacios de referencia. El ejemplo de la imagen anterior se ha configurado de la siguiente manera:

  • Un compromiso de capacidad de 1000 ranuras anuales. Esas ranuras se asignan como ranuras de referencia en la reserva etl y en la reserva dashboard.
  • Se han asignado 700 slots de referencia a la reserva etl.
  • Se han asignado 300 ranuras de referencia a la reserva dashboard.
  • Autoscala las ranuras de 600 para la reserva etl.
  • Autoescalar las plazas de 800 para la reserva del dashboard.

En el caso de la reserva etl, el número máximo de ranuras posibles es igual a las ranuras de referencia de etl (700) más las ranuras de referencia de dashboard (300, si todas las ranuras están inactivas) más el número máximo de ranuras de autoescalado (600). Por lo tanto, el número máximo de ranuras que podría usar la reserva etl en este ejemplo es 1600. Este número supera el número del compromiso de capacidad.

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

Calcular los slots disponibles

En este ejemplo, tenemos lo siguiente:

  • Un compromiso de capacidad de 1600 ranuras anuales.
  • Un tamaño máximo de reserva de 1500 (incluidas 500 ranuras de autoescalado).
  • 1000 ranuras de base asignadas a la reserva etl.

El número máximo de ranuras disponibles para la reserva es igual a las ranuras base (1000) más las ranuras inactivas comprometidas que no se dedican a las ranuras base (1600 ranuras anuales - 1000 ranuras base = 600) más el número de ranuras de autoescalado (500). Por lo tanto, el número máximo de espacios posibles en esta reserva es 2100. Los espacios con autoescalado son espacios adicionales que se suman a la capacidad comprometida.

Prácticas recomendadas para el autoescalado

  1. Cuando uses el escalador automático por primera vez, define el número de ranuras de autoescalado en un valor significativo en función del rendimiento anterior y esperado. Una vez que se haya creado la reserva, monitoriza activamente la tasa de errores, el rendimiento y la factura, y ajusta el número de ranuras de autoescalado según sea necesario.

  2. El escalador automático tiene un mínimo de 1 minuto antes de reducir la escala, por lo que es importante definir el número máximo de ranuras con escalado automático para equilibrar el rendimiento y el coste. Si el número máximo de ranuras de escalado automático es demasiado grande y tu tarea puede usar todas las ranuras para completarse en segundos, seguirás incurriendo en costes por el número máximo de ranuras durante todo el minuto. Si reduces el número máximo de ranuras a la mitad del valor actual, tu reserva se ajustará a un número inferior y el trabajo podrá usar más slot_seconds durante ese minuto, lo que reducirá el desperdicio. Para obtener ayuda a la hora de determinar los requisitos de las ranuras, consulta Monitorizar el rendimiento de los trabajos. Como alternativa para determinar tus requisitos de ranuras, consulta Ver recomendaciones de ranuras de edición.

  3. El uso de ranuras puede superar ocasionalmente la suma de las ranuras básicas y las escaladas. No se te cobrará por el uso de ranuras que supere tu base 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 que tienen varias consultas simultáneas. Evita enviar consultas de una en una, ya que cada consulta escala la reserva, que permanecerá escalada durante un mínimo de 1 minuto. Si envías consultas continuamente, lo que provoca una carga de trabajo constante, puedes definir una base y comprar una confirmación para obtener una capacidad constante a un precio con descuento.

  5. El autoescalado de BigQuery está sujeto a la disponibilidad de capacidad. BigQuery intenta satisfacer la demanda de capacidad de los clientes en función del historial de uso. Para conseguir garantías de capacidad, puedes definir una base de referencia de ranuras opcional, que es el número de ranuras garantizadas de una reserva. Con las líneas de base, los espacios publicitarios están disponibles de inmediato y pagas por ellos tanto si los usas como si no. Para asegurarte de que haya capacidad disponible para grandes demandas no orgánicas, como las que se producen en festivos con mucho tráfico, ponte en contacto con el equipo de BigQuery con varias semanas de antelación.

  6. Los espacios publicitarios de referencia siempre se cobran. Si caduca un compromiso de capacidad, es posible que tengas que ajustar manualmente la cantidad de ranuras de base de tus reservas para evitar cargos no deseados. Por ejemplo, supongamos que tienes un compromiso de 1 año con 100 ranuras y una reserva con 100 ranuras de base. El compromiso vence y no tiene un plan de renovación. Cuando caduque la confirmación, pagarás 100 ranuras básicas a la tarifa de pago por uso.

Monitorizar el autoescalado

Cuando monitorizas el uso de las ranuras con gráficos de recursos administrativos, es posible que veas muchas más ranuras escaladas que las que usas, ya que los gráficos suavizan el número de ranuras usadas durante el periodo de alineación. Para ver el uso de las ranuras de escalado automático con más detalles, reduce el periodo. De esta forma, el periodo de alineación se actualiza automáticamente a un incremento menor.

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

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

Sin embargo, si acortas el periodo de tiempo para que el periodo de alineación sea de dos segundos, verás que el escalador automático se adapta a la demanda de la carga de trabajo y muestra datos más precisos. Para ajustar el periodo, arrastra los intervalos de inicio y finalización. Para mostrar los datos de demanda de carga de trabajo más precisos, selecciona p99 en la lista Métrica.

El periodo de alineación se establece en un intervalo de dos segundos y los segmentos escalados son adecuados para la demanda de la carga de trabajo.

Para ver el uso del escalado automático con la mayor precisión posible, utiliza un periodo de alineación de entre 1 y 15 segundos.

Para obtener información sobre cómo ver el uso de tus slots, consulta Ver gráficos de recursos administrativos.

Monitorizar el autoescalado con el esquema de información

Puede usar las siguientes secuencias de comandos SQL para comprobar los segundos de ranura facturados de una edición concreta. Debes ejecutar estas secuencias de comandos en el mismo proyecto en el que se crearon las reservas. El primer script muestra los segundos de espacio facturado cubiertos por commitment_plan, mientras que el segundo muestra los segundos de espacio facturado que no están cubiertos por un compromiso.

Solo tienes que definir el valor de tres variables para ejecutar estas secuencias de comandos:

  • start_time
  • end_time
  • edition_to_check

Estos scripts están sujetos a las siguientes advertencias:

  • Las reservas y los compromisos de capacidad eliminados se quitan de las vistas de esquema de información al final del periodo de conservación de datos. Especifica un periodo reciente que no incluya reservas ni compromisos eliminados para obtener 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 comprueba el uso de espacios publicitarios cubierto por los compromisos de una edición concreta.

Despliega para ver la secuencia de comandos que calcula los segundos de espacio a partir de los compromisos.

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 comprueba el uso de espacios publicitarios no cubierto por los compromisos de una edición concreta. Este uso contiene dos tipos de espacios publicitarios: espacios publicitarios escalados y espacios publicitarios de referencia que no están cubiertos por compromisos.

Despliega para ver la secuencia de comandos que calcula los segundos de espacio no cubiertos por los compromisos

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

Monitorizar el rendimiento de los trabajos

Puede que tengas que ajustar el max_slots del autoescalado para evitar costes más elevados. La siguiente consulta proporciona contexto sobre el rendimiento de tu tarea para que puedas elegir la cantidad correcta de ranuras de autoescalado para tu carga de trabajo.

La siguiente consulta proporciona detalles sobre el rendimiento de los trabajos anteriores de tus reservas:

SELECT
    AVG(TIMESTAMP_DIFF(end_time, creation_time, MILLISECOND)) as avg_latency_ms,
    SUM(total_bytes_processed) as total_bytes,
    COUNT(*) as query_numbers,
FROM
    `PROJECT_ID.region-REGION_NAME`.INFORMATION_SCHEMA.JOBS_BY_ORGANIZATION
WHERE creation_time >= START_TIME
    AND creation_time < END_TIME
    AND (statement_type != "SCRIPT" OR statement_type IS NULL)
    AND reservation_id = RESERVATION_ID

Haz los cambios siguientes:

  • PROJECT_ID: el ID del proyecto
  • REGION_NAME: la región de tu proyecto
  • START_TIME: la hora de creación a partir de la que quiere ver los datos.
  • END_TIME: la hora de creación a partir de la que quiere dejar de ver los datos
  • RESERVATION_ID: ID de la reserva

En el siguiente ejemplo se obtienen los detalles del trabajo durante un periodo de cinco días:

SELECT
    AVG(TIMESTAMP_DIFF(end_time, creation_time, MILLISECOND)) as avg_latency_ms,
    SUM(total_bytes_processed) as total_bytes,
    COUNT(*) as query_numbers,
FROM
    `myproject.region-us`.INFORMATION_SCHEMA.JOBS_BY_ORGANIZATION
WHERE creation_time >= '2024-06-25 00:00:00-07'
    AND creation_time < '2024-06-30 00:00:00-07'
    AND (statement_type != "SCRIPT" OR statement_type IS NULL)
    AND reservation_id = reservationID

Cuotas

La suma del tamaño máximo de tus reservas no debe superar tu cuota de espacios.

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

Siguientes pasos