Pengantar penskalaan otomatis slot

Reservasi yang Anda konfigurasi untuk menggunakan penskalaan otomatis slot akan otomatis menskalakan kapasitas yang dialokasikan untuk mengakomodasi permintaan workload Anda. Saat workload Anda meningkat atau menurun, BigQuery secara dinamis menyesuaikan slot Anda ke level yang sesuai. Reservasi dengan penskalaan otomatis slot hanya tersedia dengan edisi BigQuery.

Menggunakan reservasi penskalaan otomatis

Anda tidak perlu membeli komitmen slot sebelum membuat reservasi penskalaan otomatis. Komitmen slot memberikan tarif diskon untuk slot yang digunakan secara konsisten, tetapi bersifat opsional dengan reservasi penskalaan otomatis. Untuk membuat reservasi penskalaan otomatis, Anda menetapkan jumlah slot maksimum ke reservasi (ukuran reservasi maksimum). Anda dapat mengidentifikasi jumlah maksimum slot penskalaan otomatis dengan mengurangi ukuran reservasi maksimum dengan slot dasar pengukuran opsional yang ditetapkan untuk reservasi.

Saat Anda membuat reservasi penskalaan otomatis, pertimbangkan hal berikut:

  • BigQuery menskalakan reservasi dengan kelipatan 100 hingga mencapai jumlah slot yang diperlukan untuk menjalankan tugas, atau mencapai jumlah maksimum slot yang tersedia untuk reservasi.
  • Penskalaan didasarkan pada perkiraan, dan mungkin kelebihan atau kekurangan penyediaan. Misalnya, penskala otomatis dapat diskalakan hingga 500 slot jika hanya 400 slot yang diperlukan, atau mencoba menskalakan dalam jumlah kecil saat beban kerja mungkin ditangani tanpa penskalaan.
  • Slot yang diskalakan otomatis akan dikenai biaya dengan harga komputasi kapasitas untuk edisi terkait saat meningkatkan skalanya. Anda dikenai biaya untuk jumlah slot yang diskalakan, bukan jumlah slot yang digunakan. Biaya ini berlaku meskipun tugas yang menyebabkan peningkatan skala BigQuery gagal.
  • Meskipun jumlah slot selalu diskalakan dengan kelipatan 100, jumlah slot dapat diskalakan lebih dari 100 slot dalam satu langkah. Misalnya, jika beban kerja Anda memerlukan 450 slot tambahan, BigQuery dapat mencoba menskalakan sebanyak 500 slot sekaligus untuk memenuhi persyaratan kapasitas.
  • BigQuery akan memperkecil skala jika slot yang dialokasikan melebihi jumlah slot yang diperlukan, dan kapasitas penskalaan otomatis telah stabil selama beberapa waktu.

Untuk mempelajari cara menggunakan penskalaan otomatis, lihat Menggunakan penskalaan otomatis slot.

Menggunakan reservasi dengan slot dasar pengukuran dan penskalaan otomatis

Selain menentukan ukuran reservasi maksimum, Anda dapat secara opsional menentukan jumlah slot dasar pengukuran per reservasi. Dasar pengukuran adalah jumlah minimum slot yang akan selalu dialokasikan ke reservasi, dan Anda akan selalu dikenai biaya untuk slot tersebut. Slot penskalaan otomatis hanya ditambahkan setelah semua slot dasar pengukuran (dan slot tidak ada aktivitas jika ada) digunakan. Anda dapat membagikan slot dasar pengukuran tidak ada aktivitas di satu reservasi dengan reservasi lain yang memerlukan kapasitas.

Anda dapat meningkatkan jumlah slot dasar pengukuran dalam reservasi setiap beberapa menit. Jika ingin mengurangi slot dasar pengukuran, Anda dibatasi sekali per jam jika baru-baru ini mengubah kapasitas slot dasar pengukuran dan slot dasar pengukuran melebihi slot yang di-commit. Jika tidak, Anda dapat mengurangi slot dasar pengukuran setiap beberapa menit.

Slot dasar pengukuran dan penskalaan otomatis ditujukan untuk menyediakan kapasitas berdasarkan workload terbaru Anda. Jika Anda mengantisipasi workload besar yang sangat berbeda dengan workload Anda sebelumnya, sebaiknya tingkatkan kapasitas dasar pengukuran sebelum peristiwa tersebut, daripada mengandalkan slot penskalaan otomatis untuk menutupi kapasitas workload.

Jika reservasi tidak memiliki slot dasar pengukuran atau tidak dikonfigurasi untuk meminjam slot tidak ada aktivitas dari reservasi lain, BigQuery akan mencoba melakukan penskalaan. Jika tidak, slot dasar pengukuran harus digunakan sepenuhnya sebelum penskalaan.

Reservasi menggunakan dan menambahkan slot dalam prioritas berikut:

  1. Slot dasar pengukuran.
  2. Berbagi slot tidak ada aktivitas (jika diaktifkan). Reservasi hanya dapat berbagi dasar pengukuran yang tidak ada aktivitas atau slot yang di-commit dari reservasi lain yang dibuat dengan edisi yang sama dan region yang sama.
  3. Slot penskalaan otomatis.

Dalam contoh berikut, slot diskalakan dari jumlah dasar pengukuran yang ditentukan. Reservasi etl dan dashboard memiliki ukuran dasar 700 dan 300 slot.

Contoh penskalaan otomatis tanpa komitmen.

Dalam contoh ini, reservasi etl dapat diskalakan hingga 1.300 slot (700 slot dasar pengukuran ditambah 600 slot penskalaan otomatis). Jika reservasi dashboard tidak digunakan, reservasi etl dapat menggunakan 300 slot dari reservasi dashboard jika tidak ada tugas yang berjalan di sana, sehingga menghasilkan maksimum 1.600 slot potensial.

Reservasi dashboard dapat diskalakan hingga 1.100 slot (300 slot dasar pengukuran ditambah 800 slot penskalaan otomatis). Jika reservasi etl benar-benar tidak ada aktivitas, reservasi dashboard dapat diskalakan hingga maksimum 1.800 slot (300 slot dasar pengukuran ditambah 800 slot penskalaan otomatis ditambah 700 slot tidak ada aktivitas di reservasi etl ).

Jika reservasi etl memerlukan lebih dari 700 slot dasar pengukuran yang selalu tersedia, reservasi akan mencoba menambahkan slot menggunakan metode berikut secara berurutan:

  1. 700 slot dasar pengukuran.
  2. Berbagi slot tidak ada aktivitas dengan 300 slot dasar pengukuran di reservasi dashboard. Reservasi Anda hanya membagikan slot dasar yang tidak ada aktivitas dengan reservasi lain yang dibuat dengan edisi yang sama.
  3. Meningkatkan skala 600 slot tambahan ke ukuran reservasi maksimum.

Menggunakan komitmen slot

Contoh berikut menampilkan penskalaan otomatis slot menggunakan komitmen kapasitas.

Contoh penskalaan otomatis

Seperti dasar pengukuran reservasi, komitmen slot memungkinkan Anda mengalokasikan jumlah slot tetap yang tersedia untuk semua reservasi. Tidak seperti slot dasar pengukuran, komitmen tidak dapat dikurangi selama jangka waktu yang ditentukan. Komitmen slot bersifat opsional, tetapi dapat menghemat biaya jika slot dasar pengukuran diwajibkan untuk jangka waktu yang lama.

Dalam contoh ini, Anda akan dikenai tarif standar untuk slot komitmen kapasitas. Anda akan ditagih berdasarkan tarif penskalaan otomatis untuk jumlah slot penskalaan otomatis setelah penskalaan otomatis diaktifkan dan reservasi dalam status ditingkatkan skalanya. Untuk tarif penskalaan otomatis, Anda akan ditagih untuk jumlah slot yang diskalakan, bukan jumlah slot yang digunakan.

Slot maksimum yang tersedia

Anda dapat menghitung jumlah slot maksimum yang dapat digunakan reservasi dengan menambahkan slot dasar pengukuran, jumlah maksimum slot penskalaan otomatis, dan slot apa pun dalam komitmen yang dibuat dengan edisi yang sama dan tidak tercakup oleh slot dasar pengukuran. Contoh dalam gambar sebelumnya disiapkan sebagai berikut:

  • Komitmen kapasitas 1.000 slot tahunan. Slot tersebut ditetapkan sebagai slot dasar pengukuran pada reservasi etl dan reservasi dashboard.
  • 700 slot dasar pengukuran ditetapkan ke reservasi etl.
  • 300 slot dasar pengukuran ditetapkan ke reservasi dashboard.
  • Penskalaan otomatis slot 600 untuk reservasi etl.
  • Penskalaan otomatis slot 800 untuk reservasi dashboard.

Untuk reservasi etl, jumlah maksimum slot yang memungkinkan sama dengan slot dasar pengukuran etl (700) ditambah slot dasar pengukuran dashboard (300, jika semua slot tidak ada aktivitas) ditambah jumlah maksimum slot penskalaan otomatis (600). Jadi, jumlah maksimum slot yang dapat digunakan reservasi etl dalam contoh ini adalah 1.600. Jumlah ini melebihi jumlah dalam komitmen kapasitas.

Pada contoh berikut, komitmen tahunan melebihi slot dasar pengukuran yang ditetapkan.

Menghitung slot yang tersedia

Dalam contoh ini, kita memiliki:

  • Komitmen kapasitas sebanyak 1.600 slot tahunan.
  • Ukuran reservasi maksimum 1.500 (termasuk 500 slot penskalaan otomatis).
  • 1.000 slot dasar pengukuran ditetapkan ke reservasi etl.

Jumlah maksimum slot yang tersedia untuk reservasi sama dengan slot dasar pengukuran (1.000) ditambah slot tidak ada aktivitas yang di-commit dan tidak dikhususkan untuk slot dasar pengukuran (1.600 slot tahunan - 1.000 slot dasar pengukuran = 600) ditambah jumlah slot penskalaan otomatis (500). Jadi slot potensial maksimum dalam reservasi ini adalah 2.100. Slot yang diskalakan otomatis adalah slot tambahan di atas komitmen kapasitas.

Praktik terbaik penskalaan otomatis

  1. Saat pertama kali menggunakan autoscaler, tetapkan jumlah slot penskalaan otomatis ke jumlah yang signifikan berdasarkan performa sebelumnya dan yang diperkirakan. Setelah reservasi dibuat, pantau secara aktif tingkat kegagalan, performa, dan tagihan, serta sesuaikan jumlah slot penskalaan otomatis berdasarkan kebutuhan.

  2. Perhatikan bahwa Anda dikenai biaya untuk jumlah slot yang diskalakan, bukan jumlah slot yang digunakan. Jika jumlah maksimum slot penskalaan otomatis terlalu besar, BigQuery mungkin akan menskalakan lebih banyak daripada yang Anda butuhkan, sehingga menimbulkan biaya tambahan.

    Misalnya, tugas mungkin menggunakan sejumlah besar slot pada satu titik, tetapi hanya memerlukan jumlah slot yang jauh lebih kecil. Karena BigQuery tidak segera merilis slot yang tidak digunakan, hal ini dapat mengakibatkan penurunan penggunaan jika tidak ada tugas lain di reservasi yang dapat menggunakan slot tersebut. Dengan mengurangi nilai maksimum untuk reservasi, jumlah maksimum slot yang dialokasikan akan dikurangi, sehingga menyebabkan penggunaan slot tugas menjadi lebih sedikit dan meningkatkan penggunaan tugas slot yang dialokasikan.

  3. Penggunaan slot terkadang dapat melebihi jumlah slot dasar pengukuran ditambah slot yang diskalakan. Anda tidak akan ditagih untuk penggunaan slot yang lebih besar dari slot dasar pengukuran ditambah slot yang diskalakan.

  4. Autoscaler paling efisien untuk workload yang berat dan berjalan lama, seperti workload dengan beberapa kueri serentak. Hindari mengirim kueri satu per satu ke backend, terlepas dari apakah kueri tersebut menggunakan cache atau tidak. Tanpa slot dasar pengukuran, hal ini dapat menyebabkan penskalaan yang tidak terduga dan menimbulkan biaya tinggi.

  5. Penskalaan otomatis BigQuery bergantung pada ketersediaan kapasitas. BigQuery berupaya memenuhi permintaan kapasitas pelanggan berdasarkan penggunaan historis. Untuk mencapai jaminan kapasitas, Anda dapat menetapkan dasar pengukuran slot opsional, yang merupakan jumlah slot yang dijamin dalam reservasi. Dengan dasar pengukuran, slot akan segera tersedia dan Anda membayarnya, baik Anda menggunakannya atau tidak. Guna memastikan kapasitas tersedia untuk permintaan non-organik yang besar, seperti liburan dengan traffic yang tinggi, hubungi tim BigQuery beberapa minggu sebelumnya.

  6. Slot dasar selalu terisi daya. Jika komitmen kapasitas sudah tidak berlaku, Anda mungkin perlu menyesuaikan jumlah slot dasar pengukuran di reservasi secara manual untuk menghindari biaya yang tidak diinginkan. Misalnya, pertimbangkan bahwa Anda memiliki komitmen 1 tahun dengan 100 slot dan reservasi dengan 100 slot dasar. Komitmen akan berakhir dan tidak memiliki paket perpanjangan. Setelah komitmen berakhir, Anda membayar untuk 100 slot dasar dengan tarif bayar sesuai penggunaan.

Memantau penskalaan otomatis

Saat memantau penggunaan slot dengan diagram resource administratif, Anda mungkin melihat lebih banyak slot yang diskalakan secara signifikan daripada penggunaan slot Anda karena diagram memperlancar jumlah slot yang digunakan selama periode penyelarasan singkat ini. Untuk melihat penggunaan slot penskalaan otomatis dengan detail yang lebih akurat, kurangi opsi jangka waktu. Tindakan ini otomatis memperbarui periode penyelarasan ke peningkatan yang lebih kecil.

Pada contoh berikut, diagram menampilkan lebih banyak slot yang diskalakan secara signifikan daripada permintaan workload.

Periode penyelarasan disetel ke interval satu menit dan slot yang diskalakan muncul lebih dari permintaan penggunaan slot.

Namun, jika Anda mempersingkat opsi jangka waktu sehingga periode penyelarasan menjadi dua detik, Anda dapat melihat bahwa autoscaler dapat diskalakan sesuai dengan permintaan workload dan menampilkan data yang lebih akurat. Anda dapat menyesuaikan opsi jangka waktu dengan menarik rentang awal dan akhir dari opsi jangka waktu tersebut. Untuk menampilkan data permintaan workload yang paling akurat, pilih p90 atau p99 dari daftar Metric.

Periode penyelarasan disetel ke interval dua detik dan slot yang diskalakan sesuai untuk permintaan workload.

Untuk tampilan penggunaan penskalaan otomatis yang paling akurat, gunakan periode penyelarasan antara 1 dan 15 detik. Untuk mengetahui informasi selengkapnya tentang periode penyelarasan diagram resource administratif, lihat Opsi jangka waktu.

Untuk mengetahui informasi tentang cara melihat penggunaan slot, lihat Melihat diagram resource administratif

Memantau penskalaan otomatis dengan skema informasi

Anda dapat menggunakan skrip SQL berikut untuk memeriksa detik slot yang ditagih untuk edisi tertentu. Anda harus menjalankan skrip ini dalam project yang sama tempat reservasi dibuat. Skrip pertama menampilkan detik slot yang ditagih yang dicakup oleh commitment_plan, sedangkan skrip kedua menampilkan detik slot yang ditagih yang tidak tercakup oleh komitmen.

Anda hanya perlu menetapkan nilai tiga variabel untuk menjalankan skrip ini:

  • start_time
  • end_time
  • edition_to_check

Skrip ini tunduk pada peringatan berikut:

  • Reservasi dan komitmen kapasitas yang dihapus akan dihapus dari tampilan skema informasi pada akhir periode retensi data. Tentukan periode waktu terbaru yang tidak berisi reservasi yang dihapus dan komitmen untuk hasil yang benar.

  • Hasil skrip mungkin tidak sama persis dengan tagihan karena kesalahan pembulatan kecil.

Skrip berikut memeriksa penggunaan slot yang dicakup oleh komitmen untuk edisi tertentu.

Luaskan untuk melihat skrip untuk skenario yang dibahas

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

Skrip berikut memeriksa penggunaan slot yang tidak tercakup dalam komitmen untuk edisi tertentu. Penggunaan ini berisi dua jenis slot, slot yang diskalakan dan slot dasar pengukuran yang tidak tercakup oleh komitmen.

Luaskan untuk melihat skrip untuk skenario yang tidak dicakup

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

Kuota

Jumlah ukuran reservasi maksimum tidak boleh melebihi kuota slot.

Untuk mengetahui informasi tentang kuota, lihat Kuota dan batas.

Langkah selanjutnya

  • Untuk mengetahui informasi selengkapnya tentang edisi BigQuery, lihat Pengantar BigQuery.
  • Untuk mengetahui informasi selengkapnya tentang slot, lihat Memahami slot.
  • Untuk mengetahui informasi selengkapnya tentang reservasi, lihat Pengantar reservasi.