Introdução à escala automática de slots

As reservas que configurar para usar a criação automática de escala de slots dimensionam automaticamente a capacidade atribuída para acomodar as exigências da sua carga de trabalho. À medida que a sua carga de trabalho aumenta ou diminui, o BigQuery ajusta dinamicamente os seus slots para um nível adequado. As reservas com o ajuste automático de escala de slots só estão disponíveis com as edições do BigQuery.

Use reservas de escala automática

Não tem de comprar compromissos de espaços antes de criar reservas de dimensionamento automático. Os compromissos de slots oferecem uma taxa com desconto para slots usados de forma consistente, mas são opcionais com as reservas de dimensionamento automático. Para criar uma reserva de escalamento automático, atribui à reserva um número máximo de espaços (o tamanho máximo da reserva). Pode identificar o número máximo de horários de dimensionamento automático subtraindo o tamanho máximo da reserva a quaisquer horários base opcionais atribuídos à reserva.

Quando cria reservas de dimensionamento automático, tenha em atenção o seguinte:

  • O BigQuery dimensiona as reservas quase instantaneamente até atingir o número de slots necessários para executar as tarefas ou atingir o número máximo de slots disponíveis para a reserva. Os espaços são sempre dimensionados automaticamente para um múltiplo de 50.
  • O aumento da escala baseia-se na utilização real e é arredondado para o incremento de 50 slots mais próximo.
  • Os seus slots com escalamento automático são cobrados ao preço de computação de capacidade para a edição associada durante o aumento da escala. É-lhe cobrado o número de ranhuras dimensionadas e não o número de ranhuras usadas. Esta taxa aplica-se mesmo que o trabalho que faz com que o BigQuery seja dimensionado verticalmente falhe. Por este motivo, não use o esquema de informações de empregos para fazer corresponder a faturação. Em alternativa, consulte o artigo Monitorize o ajuste automático com o esquema de informações.
  • Embora o número de espaços seja sempre dimensionado por múltiplos de 50, pode ser dimensionado em mais de 50 espaços num único passo. Por exemplo, se a sua carga de trabalho precisar de 450 slots adicionais, o BigQuery pode tentar dimensionar 450 slots de uma só vez para cumprir o requisito de capacidade.
  • O BigQuery é reduzido quando as tarefas associadas à reserva já não precisam da capacidade (sujeito a um mínimo de 1 minuto).

Qualquer capacidade com ajuste automático é mantida durante, pelo menos, 60 segundos. Este período de 60 segundos é denominado período de redução. Qualquer novo pico na capacidade repõe o período de redução, tratando todo o nível de capacidade como uma nova concessão. No entanto, se tiverem passado 60 segundos ou mais desde o último aumento da capacidade e houver menos procura, o sistema reduz a capacidade sem repor o período de redução, o que permite diminuições consecutivas sem um atraso imposto.

Por exemplo, se a capacidade de carga de trabalho inicial for dimensionada para 100 espaços, o pico é mantido durante, pelo menos, 60 segundos. Se, durante esse período de redução, a sua carga de trabalho for dimensionada para um novo pico de 200 espaços, começa um novo período de redução de 60 segundos. Se não houver um novo pico durante este período de redução, a sua carga de trabalho começa a ser reduzida no final dos 60 segundos.

Considere o seguinte exemplo detalhado: às 12:00:00, a sua capacidade inicial é dimensionada para 100 espaços e a utilização dura um segundo. Esse pico é mantido durante, pelo menos, 60 segundos, a partir das 12:00:00. Após os 60 segundos, se a nova utilização for de 50 slots, o BigQuery reduz a escala para 50 slots. Se, às 12:01:02, a nova utilização for de 0 slots, o BigQuery volta a reduzir imediatamente para 0 slots. Após o fim do período de redução, o BigQuery pode reduzir várias vezes consecutivas sem precisar de um novo período de redução.

Para saber como trabalhar com o ajuste automático de escala, consulte o artigo Trabalhe com o ajuste automático de escala de slots.

Usar reservas com base e intervalos de dimensionamento automático

Além de especificar o tamanho máximo da reserva, pode opcionalmente especificar um número base de horários disponíveis por reserva. A base é o número mínimo de espaços que são sempre atribuídos à reserva e pelos quais é sempre cobrado. Os espaços de ajuste automático só são adicionados depois de todos os espaços de base (e espaços inativos, se aplicável) serem consumidos. Pode partilhar espaços de base ociosos numa reserva com outras reservas que precisem de capacidade.

Pode aumentar o número de espaços base numa reserva a cada poucos minutos. Se quiser diminuir os seus espaços de referência, tem um limite de uma vez por hora se tiver alterado recentemente a capacidade dos espaços de referência e os espaços de referência excederem os espaços comprometidos. Caso contrário, pode diminuir os seus horários de base a cada poucos minutos.

Os slots de base e de escalabilidade automática destinam-se a fornecer capacidade com base na sua carga de trabalho recente. Se prevê uma carga de trabalho grande muito diferente das suas cargas de trabalho no passado recente, recomendamos que aumente a capacidade de base antes do evento, em vez de confiar nos espaços de dimensionamento automático para cobrir a capacidade de carga de trabalho. Se tiver um problema ao aumentar a capacidade de base, tente novamente o pedido após aguardar 15 minutos.

Se a reserva não tiver espaços base ou não estiver configurada para pedir emprestados espaços inativos a outras reservas, o BigQuery tenta dimensionar. Caso contrário, os espaços base têm de ser totalmente utilizados antes do dimensionamento.

As reservas usam e adicionam espaços na seguinte prioridade:

  1. Espaços de base.
  2. Partilha de espaços inativos (se ativada). As reservas só podem partilhar a base de referência inativa ou os espaços comprometidos de outras reservas criadas com a mesma edição e a mesma região.
  3. Ajuste automático dos espaços.

No exemplo seguinte, os espaços aumentam a partir de um valor base especificado. As reservas de etl e dashboard têm um tamanho base de 700 e 300 espaços, respetivamente.

Exemplo de escalamento automático sem compromissos.

Neste exemplo, a reserva etl pode ser dimensionada para 1300 espaços (700 espaços de base mais 600 espaços de dimensionamento automático). Se a reserva dashboard não estiver em uso, a reserva etl pode usar os 300 espaços da reserva dashboard se não estiver a ser executado nenhum trabalho, o que resulta num máximo de 1600 espaços possíveis.

A reserva de dashboard pode ser dimensionada até 1100 espaços (300 espaços de base mais 800 espaços de dimensionamento automático). Se a reserva etl estiver totalmente inativa, a reserva dashboard pode ser dimensionada para um máximo de 1800 espaços (300 espaços de base + 800 espaços de dimensionamento automático + 700 espaços inativos na reserva etl).

Se a reserva etl exigir mais de 700 espaços base, que estão sempre disponíveis, tenta adicionar espaços através dos seguintes métodos pela seguinte ordem:

  1. 700 espaços de base.
  2. Partilha de horários disponíveis com os 300 horários de referência na reserva dashboard. A sua reserva só partilha horários de base inativos com outras reservas criadas com a mesma edição.
  3. Aumentar 600 espaços adicionais até ao tamanho máximo da reserva.

Usar compromissos de slots

O exemplo seguinte mostra o dimensionamento automático de slots através de compromissos de capacidade.

Exemplo de escala automática

Tal como as bases de referência de reservas, os compromissos de horários disponíveis permitem-lhe atribuir um número fixo de horários disponíveis que estão disponíveis para todas as reservas. Ao contrário dos espaços base, não é possível reduzir um compromisso durante o prazo. Os compromissos de espaço são opcionais, mas podem poupar custos se forem necessários espaços base durante longos períodos.

Neste exemplo, é-lhe cobrada uma taxa predefinida pelos espaços de compromisso de capacidade. A taxa de dimensionamento automático é cobrada pelo número de vagas de dimensionamento automático após a ativação do dimensionamento automático e quando as reservas estão num estado de aumento de escala. Para a taxa de escalamento automático, é-lhe cobrado o número de espaços escalados e não o número de espaços usados.

O exemplo seguinte mostra as reservas quando o número de espaços de base excede o número de espaços comprometidos.

Os espaços base excedem o número de espaços comprometidos.

Neste exemplo, existem um total de 1000 posições de base entre as duas reservas, 500 da reserva etl e 500 da reserva dashboard. No entanto, o compromisso abrange apenas 800 espaços. Neste cenário, os slots em excesso são cobrados à taxa de pagamento conforme o uso (PAYG).

Número máximo de vagas disponíveis

Pode calcular o número máximo de horários disponíveis que uma reserva pode usar adicionando os horários disponíveis de base, o número máximo de horários disponíveis de dimensionamento automático e quaisquer horários disponíveis em compromissos que foram criados com a mesma edição e não estão cobertos pelos horários disponíveis de base. O exemplo na imagem anterior está configurado da seguinte forma:

  • Um compromisso de capacidade de 1000 slots anuais. Esses horários são atribuídos como horários de base na reserva etl e na reserva dashboard.
  • 700 horários base atribuídos à reserva etl.
  • 300 espaços base atribuídos à reserva dashboard.
  • Aumente automaticamente os espaços de 600 para a reserva de etl.
  • Aumente automaticamente os espaços de 800 para a reserva dashboard.

Para a reserva de etl, o número máximo de espaços possíveis é igual aos espaços base de etl (700) mais os espaços base de dashboard (300, se todos os espaços estiverem inativos) mais o número máximo de espaços de dimensionamento automático (600). Assim, o número máximo de espaços que a reserva etl poderia usar neste exemplo é 1600. Este número excede o número no compromisso de capacidade.

No exemplo seguinte, o compromisso anual excede os espaços base atribuídos.

Calcular os slots disponíveis

Neste exemplo, temos:

  • Um compromisso de capacidade de 1600 vagas anuais.
  • Um tamanho máximo de reserva de 1500 (incluindo 500 espaços de ajuste de escala automático).
  • 1000 horários base atribuídos à reserva etl.

O número máximo de espaços disponíveis para a reserva é igual aos espaços de base (1000) mais quaisquer espaços inativos comprometidos não dedicados aos espaços de base (1600 espaços anuais - 1000 espaços de base = 600) mais o número de espaços de dimensionamento automático (500). Assim, o número máximo de espaços potenciais nesta reserva é 2100. Os slots com ajuste automático são slots adicionais acima do compromisso de capacidade.

Práticas recomendadas para o dimensionamento automático

  1. Quando usar o dimensionamento automático pela primeira vez, defina o número de vagas de dimensionamento automático para um número significativo com base no desempenho passado e esperado. Depois de criar a reserva, monitorize ativamente a taxa de falhas, o desempenho e a fatura, e ajuste o número de vagas de dimensionamento automático conforme necessário.

  2. O escalador automático tem um mínimo de 1 minuto antes de reduzir a escala, por isso, é importante definir o número máximo de espaços com ajuste automático para equilibrar o desempenho e o custo. Se o número máximo de vagas de dimensionamento automático for demasiado elevado e a sua tarefa puder usar todas as vagas para concluir uma tarefa em segundos, continua a incorrer em custos pelas vagas máximas durante o minuto completo. Se reduzir o número máximo de slots para metade do valor atual, a sua reserva é dimensionada para um número inferior e a tarefa pode usar mais slot_seconds durante esse minuto, o que reduz o desperdício. Para obter ajuda na determinação dos requisitos de espaço, consulte o artigo Monitorize o desempenho das tarefas. Como abordagem alternativa para determinar os requisitos de slots, consulte o artigo Veja as recomendações de slots de edições.

  3. A utilização de espaços pode, ocasionalmente, exceder a soma do valor de referência e dos espaços dimensionados. Não lhe é cobrada a utilização de espaços superior à sua base mais espaços dimensionados.

  4. O escalonamento automático é mais eficiente para cargas de trabalho pesadas e de longa duração, como cargas de trabalho com várias consultas simultâneas. Evite enviar consultas uma de cada vez, uma vez que cada consulta dimensiona a reserva, onde permanece dimensionada durante um mínimo de 1 minuto. Se enviar consultas continuamente, o que gera uma carga de trabalho constante, definir uma base e comprar um compromisso oferece capacidade constante a um preço com desconto.

  5. O ajuste de escala automático do BigQuery está sujeito à disponibilidade de capacidade. O BigQuery tenta satisfazer a procura de capacidade dos clientes com base no histórico de utilização. Para alcançar garantias de capacidade, pode definir uma base opcional de espaços, que é o número de espaços garantidos numa reserva. Com as bases, os espaços ficam imediatamente disponíveis e paga por eles, quer os use ou não. Para garantir que a capacidade está disponível para grandes procuras não orgânicas, como feriados com tráfego elevado, contacte a equipa do BigQuery com várias semanas de antecedência.

  6. Os espaços base são sempre cobrados. Se um compromisso de capacidade expirar, pode ter de ajustar manualmente a quantidade de espaços base nas suas reservas para evitar cobranças indesejadas. Por exemplo, considere que tem um compromisso de 1 ano com 100 posições e uma reserva com 100 posições de base. O compromisso expira e não tem um plano de renovação. Quando o compromisso expira, paga 100 espaços base à tarifa de pagamento à medida do uso.

Monitorize a escala automática

Quando monitoriza a utilização de espaços com gráficos de recursos administrativos, pode ver significativamente mais espaços dimensionados do que a utilização de espaços, porque os gráficos suavizam o número de espaços usados ao longo do período de alinhamento. Para ver a utilização de espaços de ajuste automático com detalhes mais precisos, reduza a opção de intervalo de tempo. Isto atualiza automaticamente o período de alinhamento para um incremento menor.

No exemplo seguinte, o gráfico apresenta significativamente mais espaços dimensionados do que as exigências da carga de trabalho.

O período de alinhamento está definido para um intervalo de um minuto e os espaços dimensionados aparecem mais do que a utilização dos espaços exige.

No entanto, se encurtar a opção de período para que o período de alinhamento seja de 2 segundos, pode ver que o escalador automático é dimensionado de acordo com a procura da carga de trabalho e apresenta dados mais precisos. Pode ajustar a opção de intervalo de tempo arrastando os intervalos de início e fim da opção de intervalo de tempo. Para apresentar os dados de procura de carga de trabalho mais precisos, selecione p99 na lista Métrica.

O período de alinhamento está definido para um intervalo de dois segundos e os espaços dimensionados são adequados para a procura da carga de trabalho.

Para ter uma vista mais precisa da utilização do ajuste automático de escala, use um período de alinhamento entre 1 e 15 segundos.

Para ver informações sobre a utilização de slots, consulte o artigo Veja gráficos de recursos administrativos

Monitorize o dimensionamento automático com o esquema de informações

Pode usar os seguintes scripts SQL para verificar os segundos de espaço faturados para uma edição específica. Tem de executar estes scripts no mesmo projeto em que as reservas foram criadas. O primeiro script mostra os segundos de espaço faturados cobertos por commitment_plan, enquanto o segundo script mostra os segundos de espaço faturados que não estão cobertos por um compromisso.

Só tem de definir o valor de três variáveis para executar estes scripts:

  • start_time
  • end_time
  • edition_to_check

Estes scripts estão sujeitos às seguintes ressalvas:

  • As reservas e os compromissos de capacidade eliminados são removidos das vistas do esquema de informações no final do período de retenção de dados. Especifique um período recente que não contenha reservas nem compromissos eliminados para obter resultados corretos.

  • O resultado dos scripts pode não corresponder exatamente à fatura devido a pequenos erros de arredondamento.

O script seguinte verifica a utilização de espaços cobertos por compromissos para uma edição específica.

Expanda para ver o script para calcular os segundos de espaço a partir dos compromissos.

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

O script seguinte verifica a utilização de espaços não abrangidos por compromissos para uma edição específica. Esta utilização contém dois tipos de espaços, espaços dimensionados e espaços de base não abrangidos por compromissos.

Expanda para ver o script para calcular os segundos de espaço não abrangidos por compromissos

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

Monitorize o desempenho do trabalho

Pode ter de ajustar o dimensionamento automático max_slots para evitar custos mais elevados. A consulta seguinte fornece contexto sobre o desempenho do seu trabalho para que possa escolher a quantidade correta de vagas de escalamento automático para a sua carga de trabalho.

A seguinte consulta fornece detalhes sobre o desempenho de trabalhos anteriores das suas 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

Substitua o seguinte:

  • PROJECT_ID: o ID do projeto
  • REGION_NAME: a região do seu projeto
  • START_TIME: a hora de criação a partir da qual quer começar a ver os dados
  • END_TIME: a hora de criação a partir da qual quer parar de ver os dados
  • RESERVATION_ID: o ID da reserva

O exemplo seguinte obtém os detalhes do trabalho durante um período de cinco dias:

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

Quotas

A soma do tamanho máximo da reserva não deve exceder a sua quota de horários.

Para obter informações sobre quotas, consulte o artigo Quotas e limites.

O que se segue?