BigQuery Editions - zapytania zablokowane w kolejce po przejściu na sloty
Naprawa zapytań BigQuery zablokowanych w kolejce: weryfikacja capacity commitment, assignment, concurrency i autoscaling slotów.
Ten runbook opisuje diagnozowanie zapytań BigQuery zablokowanych w kolejce po migracji na slot reservations. Szczegółowy przewodnik po optymalizacji kosztów BigQuery znajdziesz w artykule Optymalizacja kosztów BigQuery - pipeline danych finansowych. W kwestii planowania capacity i konfiguracji reservations umów konsultacje.
Objaw
Zapytania pozostają w stanie PENDING zamiast przechodzić do RUNNING. Użytkownicy widzą błędy timeout lub zapytania nigdy się nie rozpoczynają:
-- Sprawdz zapytania w stanie PENDING w ostatniej godzinie
SELECT
job_id,
user_email,
state,
creation_time,
start_time,
TIMESTAMP_DIFF(COALESCE(start_time, CURRENT_TIMESTAMP()), creation_time, SECOND) AS queue_seconds,
reservation_id,
total_slot_ms
FROM `region-eu`.INFORMATION_SCHEMA.JOBS
WHERE creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR)
AND state IN ('PENDING', 'RUNNING')
ORDER BY creation_time ASC;
-- Zapytania ktore czekaly dluzej niz 60 sekund na start
SELECT
job_id,
user_email,
creation_time,
start_time,
TIMESTAMP_DIFF(start_time, creation_time, SECOND) AS wait_seconds,
reservation_id,
query
FROM `region-eu`.INFORMATION_SCHEMA.JOBS
WHERE creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 24 HOUR)
AND TIMESTAMP_DIFF(start_time, creation_time, SECOND) > 60
ORDER BY wait_seconds DESC
LIMIT 20;
# Sprawdz status konkretnego joba via bq CLI
bq show --format=prettyjson -j <project_id>:<job_id>
# Lista aktywnych jobow w projekcie
bq ls -j --all --max_results=20 --format=prettyjson <project_id>
# Typowe komunikaty bledow:
# "Resources exceeded during query execution: The query could not be executed in the allotted slot capacity"
# "Query exceeded resource limits. Slot capacity: 0 slots available for this reservation."
# Job state: PENDING (bez przejscia do RUNNING przez minuty/godziny)
Zapytania pozostają w PENDING z reservation_id wskazującym na rezerwację z niewystarczającą pojemnością. W skrajnych przypadkach joby są odrzucane z błędem Resources exceeded.
Przyczyna
Po przejściu z on-demand (autoskalowane sloty Google) na slot-based pricing (BigQuery Editions) - projekt traci dostęp do współdzielonej puli slotów Google i jest ograniczony wyłącznie do zakupionej pojemności. Zapytania blokują się, gdy:
-
Commitment zbyt mały na workload: Zakupiono np. 100 slotów, ale workload w godzinach szczytu wymaga 300-500. W modelu on-demand Google dynamicznie przydzielał tysiące slotów - po przejściu na editions projekt ma sztywny limit.
-
Assignment na złym poziomie hierarchii: Rezerwacja jest przypisana na poziomie organizacji lub folderu, ale projekt używa innej ścieżki w hierarchii GCP. Projekt nie dziedziczy przypisania i efektywnie nie ma żadnych slotów.
-
Brak autoscaling: Commitment ma ustawiony wyłącznie baseline capacity bez autoscaling. W godzinach szczytu nie ma możliwości chwilowego zwiększenia pojemności - zapytania czekają w kolejce.
-
Zły podział rezerwacji interactive vs batch: Wszystkie sloty przypisane do jednej rezerwacji obsługującej zarówno zapytania interaktywne (dashboardy, ad-hoc) jak i batch (ETL, scheduled queries). Długie joby batch blokują krótkie zapytania interaktywne.
-
Limit jednoczesnych zapytań (concurrency): BigQuery w trybie slot-based ma limit jednocześnie wykonywanych zapytań na rezerwację (domyślnie 100 concurrent queries w ramach reservation). Przy dużej liczbie małych zapytań z BI tooli - sam concurrency limit powoduje kolejkowanie, nawet jeśli sloty są wolne.
Rozwiązanie
A) Sprawdź aktualne zużycie slotów vs pojemność:
-- Zuzycie slotow w ostatniej godzinie (per minuta)
SELECT
TIMESTAMP_TRUNC(period_start, MINUTE) AS minute,
reservation_id,
SUM(period_slot_ms) / 60000 AS avg_slots_used
FROM `region-eu`.INFORMATION_SCHEMA.JOBS_TIMELINE
WHERE period_start > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR)
GROUP BY minute, reservation_id
ORDER BY minute DESC;
-- Porownanie zuzycia vs pojemnosc reservacji
SELECT
r.reservation_name,
r.slot_capacity,
r.edition,
COUNT(j.job_id) AS active_jobs,
SUM(j.total_slot_ms) / 1000 AS total_slot_seconds
FROM `region-eu`.INFORMATION_SCHEMA.RESERVATIONS r
LEFT JOIN `region-eu`.INFORMATION_SCHEMA.JOBS j
ON j.reservation_id = r.reservation_name
AND j.creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR)
GROUP BY r.reservation_name, r.slot_capacity, r.edition;
# Sprawdz capacity commitments via gcloud
gcloud beta bq capacity-commitments list \
--location=eu \
--project=<project_id> \
--format="table(name,slotCount,plan,state,edition)"
# Sprawdz reservations
gcloud beta bq reservations list \
--location=eu \
--project=<admin_project_id> \
--format="table(name,slotCapacity,edition,autoscale.maxSlots)"
# Sprawdz assignments
gcloud beta bq reservations assignments list \
--location=eu \
--project=<admin_project_id> \
--reservation=<reservation_name> \
--format="table(name,assignee,jobType,state)"
B) Zwiększ commitment lub włącz autoscaling:
# Opcja 1: Wlacz autoscaling na istniejacym reservation (zalecane)
gcloud beta bq reservations update <reservation_name> \
--location=eu \
--project=<admin_project_id> \
--autoscale-max-slots=500
# Opcja 2: Zwieksz baseline capacity (zmiana commitment)
# Najpierw sprawdz aktualny commitment
gcloud beta bq capacity-commitments list \
--location=eu \
--project=<admin_project_id>
# Utworz dodatkowy commitment (Editions - FLEX plan, mozna anulowac po 1 min)
gcloud beta bq capacity-commitments create \
--location=eu \
--project=<admin_project_id> \
--slots=200 \
--plan=FLEX \
--edition=ENTERPRISE
# Przypisz dodatkowe sloty do reservacji
gcloud beta bq reservations update <reservation_name> \
--location=eu \
--project=<admin_project_id> \
--slot-capacity=300
C) Napraw hierarchię assignment:
# Sprawdz do czego jest przypisana reservacja
gcloud beta bq reservations assignments list \
--location=eu \
--project=<admin_project_id> \
--reservation=<reservation_name>
# Jesli assignment jest na organizacji ale projekt nie dziedziczy:
# Usun stary assignment
gcloud beta bq reservations assignments delete \
<assignment_id> \
--location=eu \
--project=<admin_project_id> \
--reservation=<reservation_name>
# Utworz assignment bezposrednio na projekcie
gcloud beta bq reservations assignments create \
--location=eu \
--project=<admin_project_id> \
--reservation=<reservation_name> \
--assignee=projects/<target_project_id> \
--job-type=QUERY
# Lub na folderze zawierajacym projekt
gcloud beta bq reservations assignments create \
--location=eu \
--project=<admin_project_id> \
--reservation=<reservation_name> \
--assignee=folders/<folder_id> \
--job-type=QUERY
D) Rozdziel rezerwacje na interactive i batch:
# Utworz oddzielna reservacje dla zapytan batch/ETL
gcloud beta bq reservations create etl-batch \
--location=eu \
--project=<admin_project_id> \
--slot-capacity=100 \
--edition=ENTERPRISE
# Przypisz projekty ETL do reservacji batch
gcloud beta bq reservations assignments create \
--location=eu \
--project=<admin_project_id> \
--reservation=etl-batch \
--assignee=projects/<etl_project_id> \
--job-type=QUERY
# Glowna reservacja (interactive) - zostaw dla dashboardow i ad-hoc
# Opcjonalnie: uzyj job-type=PIPELINE dla scheduled queries
gcloud beta bq reservations assignments create \
--location=eu \
--project=<admin_project_id> \
--reservation=etl-batch \
--assignee=projects/<etl_project_id> \
--job-type=PIPELINE
# Ustaw concurrency target na reservacji interaktywnej (opcjonalne)
gcloud beta bq reservations update interactive-prod \
--location=eu \
--project=<admin_project_id> \
--concurrency=0
# concurrency=0 oznacza automatyczne zarzadzanie przez BigQuery
E) Tymczasowy powrót na on-demand (awaryjnie):
# UWAGA: Usun assignment aby projekt wrocil na on-demand billing
# To przywroci pelna wydajnosc kosztem wyzszych rachunkow
# Znajdz assignment ID
gcloud beta bq reservations assignments list \
--location=eu \
--project=<admin_project_id> \
--reservation=<reservation_name> \
--format="table(name,assignee)"
# Usun assignment (projekt natychmiast wraca na on-demand)
gcloud beta bq reservations assignments delete \
<assignment_id> \
--location=eu \
--project=<admin_project_id> \
--reservation=<reservation_name>
# Weryfikacja - projekt nie powinien miec zadnej reservacji
bq show --reservation --location=eu --project_id=<target_project_id>
# Expected: "No reservation found" = on-demand mode
Walidacja
-- 1. Brak zapytan w stanie PENDING dluzej niz 10 sekund
SELECT
COUNT(*) AS pending_jobs
FROM `region-eu`.INFORMATION_SCHEMA.JOBS
WHERE creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 10 MINUTE)
AND state = 'PENDING'
AND TIMESTAMP_DIFF(CURRENT_TIMESTAMP(), creation_time, SECOND) > 10;
-- Expected: 0
-- 2. Sredni czas oczekiwania w kolejce ponizej 5 sekund
SELECT
AVG(TIMESTAMP_DIFF(start_time, creation_time, SECOND)) AS avg_queue_seconds,
MAX(TIMESTAMP_DIFF(start_time, creation_time, SECOND)) AS max_queue_seconds,
COUNT(*) AS total_jobs
FROM `region-eu`.INFORMATION_SCHEMA.JOBS
WHERE creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 MINUTE)
AND state = 'DONE';
-- Expected: avg_queue_seconds < 5
-- 3. Zuzycie slotow nie przekracza pojemnosci reservacji
SELECT
TIMESTAMP_TRUNC(period_start, MINUTE) AS minute,
SUM(period_slot_ms) / 60000 AS slots_used
FROM `region-eu`.INFORMATION_SCHEMA.JOBS_TIMELINE
WHERE period_start > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 MINUTE)
GROUP BY minute
ORDER BY slots_used DESC
LIMIT 5;
-- Expected: slots_used <= slot_capacity reservacji (lub autoscale max)
# 4. Sprawdz slot utilization w Cloud Monitoring
gcloud monitoring metrics list \
--filter='metric.type="bigquery.googleapis.com/slots/total_available" OR metric.type="bigquery.googleapis.com/slots/allocated_for_reservation"'
# 5. Potwierdz ze reservacja i assignment sa poprawne
gcloud beta bq reservations describe <reservation_name> \
--location=eu \
--project=<admin_project_id> \
--format="json(slotCapacity,autoscale,edition)"
gcloud beta bq reservations assignments list \
--location=eu \
--project=<admin_project_id> \
--reservation=<reservation_name> \
--format="table(assignee,jobType,state)"
# Expected: state = "ACTIVE" dla wszystkich assignmentow
Jeśli brak zapytań PENDING, średni czas oczekiwania < 5s i slot utilization jest stabilne poniżej limitu - problem jest rozwiązany. Monitoruj przez 24-48h obejmując godziny szczytu (ETL + dashboardy BI), aby upewnić się że pojemność jest wystarczająca.
Zapytania BigQuery utknęły w kolejce po włączeniu slotów?
Umów bezpłatną 30-minutową rozmowę. Przejrzymy konfigurację capacity commitments, reservations i autoscaling, aby przywrócić wydajność zapytań.