Introduzione alla scalabilità automatica degli slot

Le prenotazioni che configuri per utilizzare la scalabilità automatica degli slot scalano automaticamente la capacità allocata per soddisfare le esigenze del tuo workload. Man mano che il carico di lavoro aumenta o diminuisce, BigQuery regola dinamicamente gli slot a un livello appropriato. Le prenotazioni con scalabilità automatica degli slot sono disponibili solo con le versioni di BigQuery.

Utilizzare le prenotazioni di scalabilità automatica

Non è necessario acquistare impegni di slot prima di creare prenotazioni con scalabilità automatica. Gli impegni slot offrono una tariffa scontata per gli slot utilizzati in modo coerente, ma sono facoltativi con le prenotazioni con scalabilità automatica. Per creare una prenotazione con scalabilità automatica, assegna a una prenotazione un numero massimo di slot (la dimensione massima della prenotazione). Puoi identificare il numero massimo di slot di scalabilità automatica sottraendo la dimensione massima della prenotazione a eventuali slot di riferimento facoltativi assegnati alla prenotazione.

Quando crei prenotazioni di scalabilità automatica, tieni presente quanto segue:

  • BigQuery scala le prenotazioni quasi istantaneamente fino a raggiungere il numero di slot necessari per eseguire i job oppure il numero massimo di slot disponibili per la prenotazione. Gli slot vengono sempre scalati automaticamente a un multiplo di 50.
  • Lo scale up si basa sull'utilizzo effettivo e viene arrotondato all'incremento di 50 slot più vicino.
  • Gli slot scalati automaticamente vengono addebitati in base ai prezzi di calcolo della capacità per la tua edizione associata durante lo scale up. Ti viene addebitato il numero di slot scalati, non il numero di slot utilizzati. Questo addebito si applica anche se il job che causa lo scale up di BigQuery non va a buon fine. Per questo motivo, non utilizzare lo schema delle informazioni sui lavori per la corrispondenza della fatturazione. Consulta invece Monitorare la scalabilità automatica con lo schema delle informazioni.
  • Anche se il numero di slot viene sempre scalato per multipli di 50, è possibile che venga scalato di più di 50 slot in un solo passaggio. Ad esempio, se il tuo carico di lavoro richiede 450 slot aggiuntivi, BigQuery può tentare di scalare di 450 slot contemporaneamente per soddisfare il requisito di capacità.
  • BigQuery esegue lo scale down quando i job associati alla prenotazione non hanno più bisogno della capacità (soggetto a un minimo di 1 minuto).

La capacità di scalabilità automatica viene mantenuta per almeno 60 secondi. Questo periodo di 60 secondi è chiamato finestra di riduzione. Qualsiasi nuovo picco di capacità reimposta la finestra di riduzione, trattando l'intero livello di capacità come una nuova concessione. Tuttavia, se sono trascorsi 60 secondi o più dall'ultimo aumento di capacità e la domanda è inferiore, il sistema riduce la capacità senza reimpostare la finestra di riduzione della scalabilità, consentendo riduzioni consecutive senza un ritardo imposto.

Ad esempio, se la capacità iniziale del workload viene scalata a 100 slot, il picco viene mantenuto per almeno 60 secondi. Se, durante questo periodo di riduzione, il tuo carico di lavoro viene scalato a un nuovo picco di 200 slot, inizia un nuovo periodo di riduzione di 60 secondi. Se non si verifica un nuovo picco durante questa finestra di riduzione, il tuo workload inizia afare lo scale downi al termine dei 60 secondi.

Considera il seguente esempio dettagliato: alle 12:00:00, la capacità iniziale viene scalata a 100 slot e l'utilizzo dura un secondo. Il picco viene mantenuto per almeno 60 secondi, a partire dalle ore 12:00:00. Trascorsi 60 secondi (alle 12:01:01), se il nuovo utilizzo è di 50 slot, BigQuery esegue lo scale down a 50 slot. Se alle 12:01:02 il nuovo utilizzo è di 0 slot, BigQuery esegue di nuovo immediatamente lo scale down a 0 slot. Al termine della finestra di riduzione, BigQuery puòfare lo scale downe più volte di seguito senza richiedere una nuova finestra di riduzione.

Per scoprire come utilizzare la scalabilità automatica, consulta Utilizzare la scalabilità automatica degli slot.

Utilizzo delle prenotazioni con slot di base e con scalabilità automatica

Oltre a specificare la dimensione massima della prenotazione, puoi facoltativamente specificare un numero di slot di riferimento per prenotazione. La base di riferimento è il numero minimo di slot che verranno sempre assegnati alla prenotazione e ti verranno sempre addebitati. Gli slot di scalabilità automatica vengono aggiunti solo dopo che sono stati utilizzati tutti gli slot di base (e gli slot inattivi, se applicabile). Puoi condividere gli slot di base inattivi di una prenotazione con altre prenotazioni che necessitano di capacità.

Puoi aumentare il numero di slot di base in una prenotazione ogni pochi minuti. Se vuoi ridurre gli slot di base, puoi farlo solo una volta all'ora se hai modificato di recente la capacità degli slot di base e questi superano gli slot impegnati. In caso contrario, puoi diminuire gli slot di base ogni pochi minuti.

Gli slot di riferimento e di scalabilità automatica sono pensati per fornire capacità in base al tuo workload recente. Se prevedi un carico di lavoro elevato molto diverso da quelli del recente passato, ti consigliamo di aumentare la capacità di base prima dell'evento anziché fare affidamento sugli slot di scalabilità automatica per coprire la capacità del carico di lavoro. Se riscontri un problema con l'aumento della capacità di base, riprova a inviare la richiesta dopo 15 minuti.

Se la prenotazione non ha slot di base o non è configurata per prendere in prestito slot inattivi da altre prenotazioni, BigQuery tenta di scalare. In caso contrario, gli slot di base devono essere utilizzati completamente prima dello scaling.

Le prenotazioni utilizzano e aggiungono slot con la priorità seguente:

  1. Slot di riferimento.
  2. Condivisione di slot inattivi (se abilitata). Le prenotazioni possono condividere solo slot di base inattivi o impegnati di altre prenotazioni create con la stessa edizione e la stessa regione.
  3. Slot a scalabilità automatica.

Nell'esempio seguente, gli slot vengono scalati da un importo di base specificato. Le prenotazioni etl e dashboard hanno una dimensione di base di 700 e 300 slot rispettivamente.

Esempio di scalabilità automatica senza impegni.

In questo esempio, la prenotazione etl può essere scalata a 1300 slot (700 slot di base di riferimento più 600 slot di scalabilità automatica). Se la prenotazione dashboard non è in uso, la prenotazione etl può utilizzare i 300 slot della prenotazione dashboard se non è in esecuzione alcun job, per un massimo di 1600 slot possibili.

La prenotazione dashboard può essere scalata a 1100 slot (300 slot di riferimento più 800 slot con scalabilità automatica). Se la prenotazione etl è completamente inattiva, la prenotazione dashboard può scalare fino a un massimo di 1800 slot (300 slot di base di riferimento più 800 slot di scalabilità automatica più 700 slot inattivi nella prenotazione etl).

Se la prenotazione etl richiede più di 700 slot di base, che sono sempre disponibili, tenta di aggiungere slot utilizzando i seguenti metodi in ordine:

  1. 700 slot di riferimento.
  2. Condivisione degli slot inattivi con i 300 slot di riferimento nella prenotazione dashboard. La tua prenotazione condivide solo gli slot di base inattivi con altre prenotazioni create con la stessa edizione.
  3. Aumento di 600 slot aggiuntivi fino alla dimensione massima della prenotazione.

Utilizzo degli impegni slot

L'esempio seguente mostra la scalabilità automatica degli slot utilizzando gli impegni di capacità.

Esempio di scalabilità automatica

Come le baseline di prenotazione, gli impegni di slot ti consentono di allocare un numero fisso di slot disponibili per tutte le prenotazioni. A differenza degli slot di riferimento, un impegno non può essere ridotto durante il periodo. Gli impegni slot sono facoltativi, ma possono consentire di risparmiare sui costi se gli slot di riferimento sono necessari per periodi di tempo prolungati.

In questo esempio, ti viene addebitata una tariffa predefinita per gli slot di impegno di capacità. Ti viene addebitato l'importo alla tariffa di scalabilità automatica per il numero di slot di scalabilità automatica dopo l'attivazione della scalabilità automatica e le prenotazioni sono in uno stato di scalabilità aumentata. Per la tariffa di scalabilità automatica, ti viene addebitato il numero di slot scalati, non il numero di slot utilizzati.

Il seguente esempio mostra le prenotazioni quando il numero di slot di base supera il numero di slot di impegno.

Gli slot di riferimento superano il numero di slot impegnati.

In questo esempio, ci sono un totale di 1000 slot di riferimento tra le due prenotazioni, 500 dalla prenotazione etl e 500 dalla prenotazione dashboard. Tuttavia, l'impegno copre solo 800 slot. In questo scenario, gli slot in eccesso vengono addebitati alla tariffa pay as you go (PAYG).

Numero massimo di slot disponibili

Puoi calcolare il numero massimo di slot che una prenotazione può utilizzare sommando gli slot di riferimento, il numero massimo di slot con scalabilità automatica e gli slot negli impegni creati con la stessa edizione e non coperti dagli slot di riferimento. L'esempio nell'immagine precedente è configurato come segue:

  • Un impegno di capacità di 1000 slot annuali. Questi slot vengono assegnati come slot di riferimento nella prenotazione etl e nella prenotazione dashboard.
  • 700 slot di riferimento assegnati alla prenotazione etl.
  • 300 slot di riferimento assegnati alla prenotazione dashboard.
  • Slot a scalabilità automatica di 600 per la prenotazione etl.
  • Slot a scalabilità automatica di 800 per la prenotazione dashboard.

Per la prenotazione etl, il numero massimo di slot possibili è uguale a gli slot di riferimento etl (700) più gli slot di riferimento dashboard (300, se tutti gli slot sono inattivi) più il numero massimo di slot con scalabilità automatica (600). Pertanto, il numero massimo di slot che la prenotazione etl potrebbe utilizzare in questo esempio è 1600. Questo numero supera quello dell'impegno di capacità.

Nell'esempio seguente, l'impegno annuale supera gli slot di base assegnati.

Calcolo degli slot disponibili

In questo esempio, abbiamo:

  • Un impegno di capacità di 1600 slot annuali.
  • Una dimensione massima della prenotazione di 1500 (inclusi 500 slot di scalabilità automatica).
  • 1000 slot di riferimento assegnati alla prenotazione etl.

Il numero massimo di slot disponibili per la prenotazione è uguale agli slot di base (1000) più gli slot inattivi impegnati non dedicati agli slot di base (1600 slot annuali - 1000 slot di base = 600) più il numero di slot con scalabilità automatica (500). Quindi, il numero massimo potenziale di slot in questa prenotazione è 2100. Gli slot con scalabilità automatica sono slot aggiuntivi rispetto all'impegno di capacità.

Best practice per la scalabilità automatica

  1. Quando utilizzi per la prima volta il gestore della scalabilità automatica, imposta il numero di slot di scalabilità automatica su un numero significativo in base al rendimento passato e previsto. Una volta creata la prenotazione, monitora attivamente il tasso di errore, il rendimento e la fattura e regola il numero di slot di scalabilità automatica in base alle esigenze.

  2. Il gestore della scalabilità automatica ha un minimo di 1 minuto prima di ridurre la scalabilità, quindi è importante impostare il numero massimo di slot scalati automaticamente per bilanciare prestazioni e costi. Se il numero massimo di slot a scalabilità automatica è troppo elevato e il job può utilizzare tutti gli slot per completare un job in pochi secondi, i costi per gli slot massimi vengono comunque addebitati per l'intero minuto. Se riduci gli slot massimi alla metà dell'importo attuale, la prenotazione viene scalata a un numero inferiore e il job può utilizzare più slot_seconds durante quel minuto, riducendo gli sprechi. Per assistenza nella determinazione dei requisiti degli slot, vedi Monitorare il rendimento dei job. Per un approccio alternativo alla determinazione dei requisiti degli slot, consulta Visualizzare i consigli sugli slot delle versioni.

  3. L'utilizzo degli slot può occasionalmente superare la somma degli slot di base più quelli scalati. Non ti viene addebitato l'utilizzo di slot superiore alla base di riferimento più gli slot scalati.

  4. Il gestore della scalabilità automatica è più efficiente per i carichi di lavoro pesanti e di lunga durata, ad esempio i carichi di lavoro con più query simultanee. Evita di inviare query una alla volta, poiché ogni query scala la prenotazione in cui rimarrà scalata per un minimo di 1 minuto. Se invii continuamente query, causando un carico di lavoro costante, l'impostazione di una baseline e l'acquisto di un impegno forniscono una capacità costante a un prezzo scontato.

  5. La scalabilità automatica di BigQuery è soggetta alla disponibilità di capacità. BigQuery tenta di soddisfare la domanda di capacità dei clienti in base all'utilizzo storico. Per ottenere garanzie di capacità, puoi impostare una base di riferimento facoltativa per gli slot, ovvero il numero di slot garantiti in una prenotazione. Con le baseline, gli slot sono immediatamente disponibili e li paghi indipendentemente dal fatto che li utilizzi o meno. Per assicurarti che la capacità sia disponibile per richieste di grandi dimensioni e non organiche, come le festività con traffico elevato, contatta il team BigQuery con diverse settimane di anticipo.

  6. Gli slot di riferimento vengono sempre addebitati. Se un impegno di capacità scade, potresti dover modificare manualmente la quantità di slot di riferimento nelle tue prenotazioni per evitare addebiti indesiderati. Ad esempio, supponiamo di avere un impegno di 1 anno con 100 slot e una prenotazione con 100 slot di base. L'impegno scade e non prevede un piano di rinnovo. Una volta scaduto l'impegno, paghi 100 slot di base alla tariffa pay as you go.

Monitorare la scalabilità automatica

Quando monitori l'utilizzo degli slot con i grafici delle risorse amministrative, potresti notare un numero di slot scalati significativamente superiore all'utilizzo degli slot, perché i grafici uniformano il numero di slot utilizzati nel periodo di allineamento. Per visualizzare l'utilizzo degli slot di scalabilità automatica con dettagli più precisi, riduci l'opzione dell'intervallo di tempo. In questo modo, il periodo di allineamento viene aggiornato automaticamente a un incremento più piccolo.

Nell'esempio seguente, il grafico mostra un numero di slot scalati notevolmente superiore a quello richiesto dal carico di lavoro.

Il periodo di allineamento è impostato su un intervallo di un minuto e gli slot scalati
vengono visualizzati più volte rispetto a quanto richiesto
dall'utilizzo degli slot.

Tuttavia, se accorci l'opzione del periodo di tempo in modo che il periodo di allineamento sia di due secondi, puoi notare che lo scalatore automatico si adatta alla domanda del workload e mostra dati più accurati. Puoi regolare l'opzione dell'intervallo di tempo trascinando gli intervalli di inizio e fine dell'opzione dell'intervallo di tempo. Per visualizzare i dati più accurati sulla domanda di workload, seleziona p99 dall'elenco Metrica.

Il periodo di allineamento è impostato su un intervallo di due secondi e gli slot scalati
sono appropriati per la domanda
del workload.

Per una visualizzazione più accurata dell'utilizzo della scalabilità automatica, utilizza un periodo di allineamento compreso tra 1 e 15 secondi.

Per informazioni sulla visualizzazione dell'utilizzo degli slot, vedi Visualizzare i grafici delle risorse amministrative.

Monitora la scalabilità automatica con lo schema delle informazioni

Puoi utilizzare i seguenti script SQL per controllare i secondi di slot fatturati per una determinata edizione. Devi eseguire questi script nello stesso progetto in cui sono state create le prenotazioni. Il primo script mostra i secondi di slot fatturati coperti da commitment_plan, mentre il secondo mostra i secondi di slot fatturati non coperti da un impegno.

Per eseguire questi script, devi impostare solo il valore di tre variabili:

  • start_time
  • end_time
  • edition_to_check

Questi script sono soggetti alle seguenti limitazioni:

  • Le prenotazioni e gli impegni di capacità eliminati vengono rimossi dalle visualizzazioni dello schema delle informazioni al termine del periodo di conservazione dei dati. Specifica un periodo di tempo recente che non contenga prenotazioni ed impegni eliminati per ottenere risultati corretti.

  • Il risultato degli script potrebbe non corrispondere esattamente alla fattura a causa di piccoli errori di arrotondamento.

Il seguente script controlla l'utilizzo degli slot coperti dagli impegni per una determinata edizione.

Espandi per visualizzare lo script per calcolare i secondi di slot a partire dagli impegni.

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

Il seguente script controlla l'utilizzo degli slot non coperti dagli impegni per una determinata edizione. Questo utilizzo contiene due tipi di slot: slot scalati e slot di base non coperti dagli impegni.

Espandi per visualizzare lo script per calcolare i secondi di slot non coperti dagli impegni

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

Monitorare il rendimento dei job

Potresti dover regolare la scalabilità automatica max_slots per evitare costi più elevati. La seguente query fornisce il contesto sulle prestazioni del tuo job in modo da poter scegliere la quantità corretta di slot di scalabilità automatica per il tuo workload.

La seguente query fornisce dettagli sul rendimento passato dei tuoi lavori di prenotazione:

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

Sostituisci quanto segue:

  • PROJECT_ID: l'ID progetto
  • REGION_NAME: la regione del tuo progetto
  • START_TIME: l'ora di creazione da cui vuoi iniziare a visualizzare i dati
  • END_TIME: l'ora di creazione in cui vuoi interrompere la visualizzazione dei dati
  • RESERVATION_ID: l'ID prenotazione

Il seguente esempio recupera i dettagli del job in un periodo di cinque giorni:

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

Quote

La somma delle dimensioni massime della prenotazione non deve superare la quota di slot.

Per informazioni sulle quote, consulta Quote e limiti.

Passaggi successivi