Introdução ao escalonamento automático de slots
As reservas que você configura para usar o escalonamento automático de slots escalonam automaticamente a capacidade alocada para acomodar as demandas de carga de trabalho. À medida que a carga de trabalho aumenta ou diminui, o BigQuery ajusta dinamicamente os slots para um nível apropriado. As reservas com escalonamento automático de slots estão disponíveis apenas com as edições do BigQuery.
Usar reservas de escalonamento automático
Você não precisa adquirir compromissos de slot antes de criar reservas de escalonamento automático. Os compromissos de slot fornecem um preço com desconto para slots usados de forma consistente, mas são opcionais com reservas de escalonamento automático. Para criar uma reserva de escalonamento automático, atribua uma reserva a um número máximo de slots (o tamanho máximo da reserva). Para identificar o número máximo de slots de escalonamento automático, subtraia o tamanho máximo da reserva de todos os slots de valor de referência opcionais atribuídos à reserva.
Ao criar reservas de escalonamento automático, considere o seguinte:
- O BigQuery escalona reservas por múltiplos de 100 até atingir o número de slots necessários para executar os jobs ou atingir o número máximo de slots disponíveis para a reserva.
- O aumento é baseado em uma estimativa e pode ser provisionado em excesso ou de forma insuficiente. Por exemplo, o escalonador automático pode ser escalonado para 500 slots quando apenas 400 forem necessários ou tentar escalonar uma pequena quantidade quando a carga de trabalho puder ser processada sem escalonar.
- Os slots com escalonamento automático são cobrados de acordo com os preços de capacidade de computação da edição associada durante o escalonamento vertical. Você é cobrado pelo número de slots escalonados, não pelo número de slots usados. Essa cobrança será aplicada mesmo se o job que faz o BigQuery escalonar verticalmente falhar.
- O número de slots sempre é escalonado por múltiplos de 100, mas é possível escalonar mais de 100 slots em uma etapa. Por exemplo, se sua carga de trabalho exigir mais 450 slots, o BigQuery pode tentar escalonar por 500 slots de uma vez para atender ao requisito de capacidade.
- O BigQuery reduz escala vertical quando os slots alocados excedem o número de slots necessários e a capacidade de escalonamento automático permanece estável por algum tempo.
Para saber como trabalhar com o escalonamento automático, consulte Trabalhar com escalonamento automático de slots.
Como usar reservas com slots de valor de referência e escalonamento automático
Além de especificar o tamanho máximo da reserva, é possível opcionalmente determinar um número de referência de slots por reserva. O valor de referência é o número mínimo de slots que sempre serão alocados na reserva e que sempre serão cobrados. Os slots de escalonamento automático são adicionados somente depois que todos os slots de linha de base (e os slots inativos, se aplicável) são consumidos. É possível compartilhar slots de valor de referência inativos em uma reserva com outras que precisam de capacidade.
É possível aumentar o número de slots de valor de referência em uma reserva a cada poucos minutos. Se você quiser diminuir os slots de valor de referência, terá o limite de uma hora por hora se tiver alterado recentemente a capacidade de slots do valor de referência e os slots de referência excederem os slots confirmados. Caso contrário, é possível diminuir os slots de valor de referência em intervalos de alguns minutos.
Os slots de valor de referência e de escalonamento automático foram projetados para fornecer capacidade com base na sua carga de trabalho recente. Se você antecipar uma grande carga de trabalho que seja muito diferente das suas cargas de trabalho recentes, recomendamos aumentar a capacidade de valor de referência antes do evento, em vez de depender de slots de escalonamento automático para cobrir a capacidade.
Se a reserva não tiver slots de valor de referência ou não estiver configurada para emprestar slots inativos de outras reservas, o BigQuery tentará escalonar. Caso contrário, os slots de valor de referência precisam ser totalmente utilizados antes do escalonamento.
As reservas usam e adicionam slots na seguinte prioridade:
- Slots de referência:
- Compartilhamento de slots inativos (se ativado). As reservas só podem compartilhar valor de referência ocioso ou slots confirmados de outras reservas que foram criadas com a mesma edição e a mesma região.
- Slots de escalonamento automático.
No exemplo a seguir, os slots são dimensionados de acordo com um valor de referência especificado. As reservas etl
e dashboard
têm um tamanho de referência de 700 e 300 slots, respectivamente.
Neste exemplo, a reserva etl
pode ser dimensionada para 1.300 slots (700 slots de valor de referência mais 600 slots de escalonamento automático). Se a reserva dashboard
não estiver em uso,
a reserva etl
poderá usar os 300 slots da reserva dashboard
se nenhum job estiver em execução lá, levando a um máximo de 1.600 slots possíveis slots.
A reserva dashboard
pode ser escalonada para 1.100 slots (300 slots de valor de referência mais
800 slots de escalonamento automático). Se a reserva etl
estiver totalmente inativa, a reserva dashboard
poderá ser escalonada para, no máximo, 1.800 slots (300 slots de valor de referência, 800 slots de escalonamento automático, mais 700 slots inativos na reserva etl
).
Se a reserva etl
exigir mais de 700 slots de valor de referência, que estão
sempre disponíveis, ela tentará adicionar slots usando os seguintes métodos na
ordem:
- 700 slots de referência.
- Compartilhamento de slot inativo com os
300 slots de valor de referência na reserva
dashboard
. Sua reserva compartilha apenas slots de valor de referência ociosos com outras reservas criadas com a mesma edição. - Escalonar verticalmente mais 600 slots para o tamanho máximo de reserva.
Como usar compromissos de slot
No exemplo a seguir, mostramos o escalonamento automático de slots usando compromissos de capacidade.
Assim como os valores de referência de reserva, os compromissos de slot permitem alocar um número fixo de slots disponíveis para todas as reservas. Ao contrário dos slots de valor de referência, não é possível reduzir um compromisso durante o prazo. Os compromissos de slot são opcionais, mas podem economizar custos se forem necessários slots de valor de referência por longos períodos.
Neste exemplo, é cobrada uma taxa predefinida pelos slots de compromisso de capacidade. Você será cobrado pela taxa de escalonamento automático pelo número de slots de escalonamento automático após a ativação do escalonamento automático e as reservas em um estado otimizado. Para a taxa de escalonamento automático, você é cobrado pelo número de slots escalonados, não pelo número de slots usados.
Máximo de slots disponíveis
É possível calcular o número máximo de slots que uma reserva pode usar adicionando os slots de valor de referência, o número máximo de slots de escalonamento automático e todos os slots em confirmações que foram criadas com escalonamento automático de slots e não são cobertas pelo slots de referência. O exemplo na imagem anterior é configurado da seguinte maneira:
- Um compromisso de capacidade de 1.000 slots anuais. Esses slots são atribuídos como
slots de referência na reserva
etl
e na reservadashboard
. - 700 slots de valor de referência atribuídos à reserva
etl
. - 300 slots de valor de referência atribuídos à reserva
dashboard
. - Escalonamento automático de slots de 600 para a reserva
etl
. - Escalonamento automático de slots de 800 para a reserva
dashboard
.
Para a reserva etl
, o número máximo de slots possível é igual aos
slots de referência etl
(700) mais os slots de valor de referência dashboard
(300, se
todos os slots estiverem inativos). mais o número máximo de slots de escalonamento automático (600). Portanto, o número máximo de slots que a reserva etl
pode usar neste exemplo é 1.600. Esse número excede o do compromisso de capacidade.
No exemplo a seguir, o compromisso anual excede os slots de valor de referência atribuídos.
Neste exemplo, temos:
- Um compromisso de capacidade de 1.600 slots anuais.
- Um tamanho máximo de reserva de 1.500 (incluindo 500 slots de escalonamento automático).
- 1.000 slots de valor de referência atribuídos à reserva
etl
.
O número máximo de slots disponíveis para a reserva é igual aos slots de valor de referência (1.000), mais os slots inativos com compromisso não dedicados aos slots de valor de referência (1.600 slots anuais - 1.000 slots de valor de referência = 600) mais o número de slots de escalonamento automático (500). Portanto, o número máximo de slots possíveis nessa reserva é de 2.100. Os slots com escalonamento automático são slots adicionais acima do compromisso de capacidade.
Práticas recomendadas para escalonamento automático
Ao usar o escalonador automático pela primeira vez, defina o número de slots de escalonamento automático como um número significativo com base no desempenho anterior e esperado. Depois que a reserva for criada, monitore ativamente a taxa de falhas, o desempenho e o faturamento e ajuste o número de slots de escalonamento automático conforme necessário.
A cobrança é feita pelo número de slots escalonados, e não pelo número de slots usados. Se o número máximo de slots de escalonamento automático for muito grande, o BigQuery poderá escalonar mais do que o necessário, gerando custos adicionais.
Por exemplo, um job pode usar um grande número de slots em um ponto, mas só precisa de um número significativamente menor. Como o BigQuery não libera slots não utilizados imediatamente, isso poderá resultar em menor utilização se nenhum outro job na reserva puder usá-los. Ao reduzir o valor máximo de uma reserva, o número máximo de slots alocados é reduzido, o que diminui o uso de slots de job e melhora a utilização de slots alocados.
De vez em quando, o uso de slots pode exceder a soma do valor de referência mais os slots dimensionados. Você não vai receber cobranças pelo uso de slots maior que o valor de referência mais os slots escalonados.
O autoescalador é mais eficiente para cargas de trabalho pesadas e de longa duração, como cargas de trabalho com várias consultas simultâneas. Evite enviar uma consulta de cada vez ao back-end, mesmo que elas não usem o cache. Sem slots de valor de referência, isso pode causar um escalonamento inesperado e gerar altos custos.
O escalonamento automático do BigQuery está sujeito à disponibilidade de capacidade. O BigQuery tenta atender à demanda de capacidade do cliente com base no uso histórico. Para alcançar as garantias de capacidade, defina um valor de referência de slot opcional, que é o número de slots garantidos em uma reserva. Com os valores de referência, os slots ficam disponíveis imediatamente e você paga por eles, independentemente de usá-los ou não. Para garantir que a capacidade esteja disponível para grandes demandas inorgânicas, como feriados de alto tráfego, entre em contato com a equipe do BigQuery com várias semanas de antecedência.
Os slots de valor de referência sempre são carregados. Se um compromisso de capacidade expirar, talvez seja necessário ajustar manualmente a quantidade de slots de valor de referência nas reservas para evitar cobranças indesejadas. Por exemplo, considere que você tem um compromisso de um ano com 100 slots e uma reserva com 100 slots de valor de referência. O compromisso expira e não tem um plano de renovação. Quando o compromisso expirar, você pagará por 100 slots de valor de referência com a taxa de pagamento por utilização.
Monitorar o escalonamento automático
Ao monitorar o uso de slots com gráficos de recursos administrativos, é possível conferir mais slots significativamente dimensionados do que o uso de slots, porque os gráficos suavizam o número de slots usados durante o período de alinhamento. Para visualizar o uso de slots de escalonamento automático com detalhes mais precisos, reduza a opção de período. Isso atualiza automaticamente o período de alinhamento para um incremento menor.
No exemplo a seguir, o gráfico mostra muito mais slots dimensionados do que as demandas da carga de trabalho.
No entanto, se você reduzir a opção de período para que o período de alinhamento seja dois segundos, o escalonador automático é escalonado de acordo com a demanda da carga de trabalho e mostra dados mais precisos. Para ajustar a opção de período, arraste os intervalos de início e término dela. Para exibir os dados de demanda de carga de trabalho mais precisos, selecione p99 na lista métrica.
Para ter a visualização mais precisa do uso do escalonamento automático, use um período de alinhamento entre 1 e 15 segundos. Para mais informações sobre o período de alinhamento dos gráficos de recursos administrativos, consulte Opção de período.
Para informações sobre como visualizar o uso de slots, consulte Ver gráficos de recursos administrativos
Monitorar o escalonamento automático com esquema de informações
É possível usar os seguintes scripts SQL para verificar os segundos de slot faturados de uma
edição específica. Execute esses scripts no mesmo projeto em que as reservas foram criadas. O primeiro script mostra os segundos de slot faturados cobertos por commitment_plan
, enquanto o segundo mostra os segundos de slot faturados que não são cobertos por um compromisso.
Você só precisa definir o valor de três variáveis para executar esses scripts:
start_time
end_time
edition_to_check
Esses scripts estão sujeitos às seguintes ressalvas:
As reservas e os compromissos de capacidade excluídos são removidos das visualizações do esquema de informações no final do período de armazenamento de dados. Especifique uma janela de tempo recente que não contenha reservas e compromissos excluídos para resultados corretos.
O resultado dos scripts pode não corresponder exatamente à fatura devido a pequenos erros de arredondamento.
O script a seguir verifica o uso de slot coberto pelos compromissos de uma edição específica.
Clique para abrir o script das situações abordadas
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 a seguir verifica o uso de slots não coberto pelos compromissos de uma edição específica. Esse uso contém dois tipos de slots: escalonados e de referência não cobertos por compromissos.
Clique para abrir o script em situações não abrangidas
/* 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
Cotas
A soma do tamanho máximo da reserva não pode exceder sua cota de slots.
Para mais informações sobre cotas, consulte Cotas e limites.
A seguir
- Para mais informações sobre as edições do BigQuery, consulte Introdução ao BigQuery.
- Para saber mais sobre slots, consulte Entender os slots.
- Para mais informações sobre reservas, consulte Introdução às reservas.