Rachunki BigQuery zaskakują zespoły, bo BigQuery jest tanie w większości scenariuszy, a spektakularnie drogie w kilku. Różnica między 20 USD miesięcznie a 2 000 USD miesięcznie to zwykle jedno złe scheduled query uderzające w niefiltrowaną tabelę GA4 events co godzinę.
Ten poradnik pokrywa rzeczywistą strukturę kosztów, siedem optymalizacji, które najbardziej przesuwają wskazówkę, i konkretne pułapki GA4 Export, które generują zaskakujące faktury. Na podstawie audytów kosztów BigQuery i ratunków pipeline'ów, które robiłem dla europejskich e-commerce, SaaS i agencji od 2022 roku.
Jeśli oceniasz, czy BigQuery w ogóle ma sens, zacznij od poradnika podstaw BigQuery. Ten artykuł zakłada, że już używasz BigQuery i chcesz trzymać rachunek pod kontrolą.
Kluczowe wnioski
Cennik on-demand: 5 USD za TB zeskanowanych, 0,02 USD za GB/miesiąc storage, 0,01 USD/GB dla danych niezmienianych 90+ dni. Pierwsze 1 TB query + 10 GB storage to free tier.
Największa wygrana to partition filtering z
_TABLE_SUFFIXna tabelach eventów GA4. Dodanie jednego klauzula WHERE może zredukować zapytanie z 500 GB do 5 GB.
SELECT *na schema GA4 to druga największa dziura kosztowa. Wyspecyfikuj kolumny, których faktycznie używasz.Streaming inserts kosztują 10× więcej niż batch inserts. Jeśli real-time nie jest wymagane, wsadowo wszystko.
Cache hits są darmowe i trzymane 24 godziny. Powtórzone zapytania z dashboardów Looker Studio często uderzają w cache; strukturyzuj dashboardy, żeby to wykorzystywać.
Ustaw alert billingowy na 50% budżetu. Połowa "niespodziewanych" rachunków BigQuery mogła być złapana na 30% miesiąca, gdyby ktoś to obserwował.
Jak naprawdę działa cennik BigQuery
Trzy komponenty kosztowe. W kolejności typowego wpływu na Twój rachunek:
1. Query processing, 5 USD za TB zeskanowanych danych (on-demand)
Za każdym razem, gdy zapytanie się uruchomi, BigQuery raportuje "bytes processed", dosłowną ilość danych, którą zapytanie musiało zeskanować z dysku. Płacisz 5 USD za 1 099 511 627 776 bajtów (1 TB). Free tier pokrywa pierwsze 1 TB miesięcznie per billing account.
Krytyczny szczegół: BigQuery jest kolumnowe. Zapytanie typu SELECT user_pseudo_id FROM events na tabeli 500 GB skanuje tylko kolumnę user_pseudo_id, nie całe 500 GB. To typowo 1-5% całkowitego rozmiaru. Dlatego specyfikowanie kolumn ma tak duże znaczenie, SELECT * skanuje 100% każdej kolumny w każdym zwracanym wierszu.
2. Storage, 0,02 USD za GB/miesiąc (active), 0,01 USD (long-term)
Dane niezmieniane przez 90+ kolejnych dni automatycznie przechodzą do long-term storage tier (50% taniej). Nie wymaga akcji. Jeśli tabela dostanie UPDATE albo nowy wiersz, wraca do active. Dzienne tabele GA4 Export (events_YYYYMMDD) przestają dostawać zapisy po zakończeniu swojego dnia, więc automatycznie trafiają do long-term storage po 90 dniach.
Dla typowego mid-market e-commerce z 3 latami GA4 Export: 30 GB active + 250 GB long-term = 30 × 0,02 + 250 × 0,01 = 3,10 USD/miesiąc. Storage rzadko jest drogą linią.
3. Streaming inserts, 0,01 USD za 200 MB
Tylko jeśli używasz streaming API dla zapisów real-time. GA4 Export ma zarówno daily batch (darmowy) i intraday streaming (są opłaty). Większość zespołów nie potrzebuje intraday; jeśli nie, wyłącz streaming i oszczędź.
Co NIE jest wliczone
- Darmowe: uploady storage, operacje metadanych, zapytania, które padły albo zostały anulowane, zapytania serwowane z cache, statements DDL (CREATE TABLE itp.), DML na tabelach pod 10 MB.
- Minimalna opłata per zapytanie: 10 MB. Zapytanie skanujące 500 KB wciąż kosztuje jak 10 MB. Mnóstwo drobnych zapytań się sumuje, jeśli uruchamiasz tysiące dziennie.
Siedem optymalizacji, które mają największe znaczenie
Posortowane po typowym wpływie kosztowym na workload GA4 Export.
1. Partition filtering z _TABLE_SUFFIX (największa wygrana)
GA4 eksportuje dane jako jedna tabela na dzień: events_20251001, events_20251002 itd. Wildcard events_* pozwala pytać przez dni. Bez filtra suffix wildcard skanuje tabelę każdego dnia.
Źle (skanuje 365 dni):
SELECT COUNT(DISTINCT user_pseudo_id)
FROM project.analytics_123.events_*
WHERE event_name = 'purchase'
Dobrze (skanuje 7 dni):
SELECT COUNT(DISTINCT user_pseudo_id)
FROM project.analytics_123.events_*
WHERE _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY))
AND FORMAT_DATE('%Y%m%d', CURRENT_DATE())
AND event_name = 'purchase'
Dla e-commerce z 100 000 sesji dziennie, to 52× mniej zeskanowanych danych, ta sama odpowiedź. Sama ta optymalizacja typowo obniża koszty zapytań GA4 Export o 70-90%.
2. SELECT konkretnych kolumn, nigdy *
Schema GA4 Export ma zagnieżdżone kolumny (event_params, user_properties, items). SELECT * zmusza BigQuery do pobrania wszystkich, nawet jeśli chcesz tylko event_name.
Źle: SELECT FROM events_, skanuje każdą kolumnę w każdym wierszu.
Dobrze: SELECT event_name, user_pseudo_id, event_timestamp FROM events_*, skanuje trzy kolumny.
Dla tabel GA4 kolumny, które wyciągasz z event_params przez UNNEST, też dodają do kosztu skanu. Używaj tylko parametrów, których faktycznie potrzebujesz.
3. Klastruj tabele po często filtrowanych kolumnach
Jeśli regularnie uruchamiasz zapytania filtrujące po konkretnej kolumnie (np. country albo event_name), klastruj tabelę po tej kolumnie. BigQuery fizycznie sortuje dane i może pominąć całe bloki podczas skanu.
Tabele GA4 Export są już klastrowane po event_name, event_timestamp i kilku innych, więc filtry po eventach są już tanie. Dla Twoich własnych tabel pochodnych klastruj je jawnie, kiedy je tworzysz:
CREATE TABLE my_aggregates
PARTITION BY DATE(event_timestamp)
CLUSTER BY country, event_name AS
SELECT * FROM source
4. Podgląd wyników przed uruchomieniem pełnego zapytania
BigQuery Studio pokazuje "This query will process X bytes" zanim klikniesz Run. Sprawdzaj tę liczbę za każdym razem na nieznajomym zapytaniu. Jeśli mówi 500 GB, a spodziewałeś się 5 GB, coś jest nie tak, popraw zapytanie przed wykonaniem.
Dla dashboardów, które uruchamiają zapytania w imieniu userów, loguj metrykę bytes-processed i alertuj na outliery. Dashboard, który normalnie przetwarza 10 GB, nagle przetwarzający 500 GB oznacza, że ktoś zmienił filtr albo źródło danych powyżej.
5. Wykorzystuj 24-godzinny cache zapytań
Identyczne zapytania w ciągu 24 godzin są serwowane z cache. Cache hits są darmowe i szybkie (sub-sekundowe).
W praktyce: dashboardy Looker Studio, które odświeżają się co godzinę z identycznymi parametrami, uderzają w cache 23 na 24 razy. Dashboard z 10 zapytaniami uruchamianymi co godzinę przez 10 godzin dnia pracy kosztowałby inaczej 10×10×query_size. Cache sprawia, że to 10×1×query_size. 10× oszczędności bez zmiany SQL-a.
Cache jest per-query-text; jakakolwiek zmiana w zapytaniu (nawet whitespace) unieważnia. Trzymaj generowanie zapytań deterministyczne.
6. Materializuj powtarzane agregacje
Jeśli pięć różnych dashboardów liczy "dzienny przychód per kanał", nie uruchamiaj tej samej agregacji pięć razy, zmaterializuj ją raz do małej tabeli i odpytuj tę tabelę z dashboardów.
Materialized views albo scheduled queries uruchamiane raz dziennie z GA4 Export produkują tabelę podsumowania 100 KB. Pięć dashboardów odpytujących 100 KB podsumowania kosztuje 5 × 10 MB minimum = 50 MB, versus 5 × 5 GB = 25 GB przeciwko surowej tabeli eventów. Ta sama odpowiedź, 500× taniej.
7. Daj long-term storage zrobić swoje
Dane niezmienione 90+ dni automatycznie spadają do 0,01 USD/GB/miesiąc (50% kosztu active storage). Nie walcz z tym, uruchamiając UPDATE na historycznych partycjach. Gdy dzień jest zamknięty, zostaw go.
Specyficzne pułapki GA4 Export
To są konkretne rzeczy, które generują ticketów "mój rachunek BigQuery potroił się".
Pułapka 1: Zapytania w events_intraday_, kiedy masz na myśli events_
GA4 tworzy dwie rodziny tabel: events_YYYYMMDD (sfinalizowane daily batches) i events_intraday_YYYYMMDD (bieżący dzień, streaming). Intraday to osobny zestaw tabel. Jeśli Twój dashboard przypadkowo pyta events_intraday_* bez filtra daty, skanujesz dane streaming wielokrotnie.
Bezpieczniejszy wzorzec: jawnie wybierz events_ (sfinalizowane) dla historycznych raportów, a dotykaj events_intraday_ tylko jeśli raport musi zawierać dzisiaj.
Pułapka 2: UNNEST bez powodu
Parametry eventów GA4 żyją wewnątrz zagnieżdżonej tablicy. Żeby filtrować po wartości parametru, UNNEST(event_params). To jest w porządku. Co nie jest w porządku, to unnestowanie parametrów, po których nie filtrujesz:
Źle: SELECT event_name, (SELECT value.string_value FROM UNNEST(event_params) WHERE key='page_title') FROM events_*
To pobiera całą tablicę event_params dla każdego wiersza. Jeśli większość wierszy nie ma parametru page_title, wciąż zapłaciłeś za skan całej tablicy.
Lepiej: Pre-filtruj po event_name = 'page_view', żeby tylko wiersze page view były unnestowane.
Pułapka 3: Scheduled queries na pełnej historii zamiast wczoraj
Scheduled Queries są świetne do budowania dziennych agregatów. Typowy błąd: pisanie scheduled query jako "przebuduj pełną agregację od początku czasu" zamiast "dopisz wczorajsze dane do istniejącego agregatu".
Wzorzec rebuild (zły): CREATE OR REPLACE TABLE my_aggs AS SELECT ... FROM events_*. Uruchamia się codziennie. Skanuje całą historię codziennie. Koszty się mnożą.
Wzorzec append (dobry): INSERT INTO my_aggs SELECT ... FROM events_* WHERE _TABLE_SUFFIX = FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)). Uruchamia się codziennie, skanuje tylko jeden dzień.
Pułapka 4: Subquery cross-join ogromnych tabel
Joinowanie GA4 Export do samej siebie (np. znajdowanie userów, których pierwszy event był X, a potem zrobili Y) może wybuchnąć, jeśli zrobione naiwnie. Użyj window functions po sesjach albo węższych filtrów w każdym subquery przed joinem.
Mini-historia: 4 000 EUR do 400 EUR w trzy godziny
Kiedy Alicja, head of analytics w polskim brandzie D2C, pokazała mi swój rachunek Google Cloud w lipcu 2025, BigQuery zjadało 3 847 EUR miesięcznie. Jej infrastruktura to był standardowy GA4 Export + siedem dashboardów Looker Studio + trzy scheduled queries + jeden custom reporting pipeline.
Wyniki audytu:
- Trzy z scheduled queries przebudowywały pełne agregaty codziennie zamiast dopisywać wczorajsze dane. 80% rachunku brało się z tych trzech zapytań.
- Dwa dashboardy Lookera były skonfigurowane z 5-minutowym interwałem odświeżania, non-stop cache-busting. Raz na godzinę wystarczałoby jej audiencji.
- Jeden dashboard robił
SELECTna wildcardevents_bez filtra suffix. Pojedyncze zapytanie, 47 GB zeskanowane, uruchamiane 40 razy dziennie.
Fixy (3 godziny pracy):
- Przepisaliśmy scheduled queries jako append-only incrementals
- Zmieniliśmy interwały odświeżania dashboardów na godzinne
- Dodaliśmy filter
_TABLE_SUFFIXi konkretną listę kolumn do złego dashboardu
Następny miesięczny rachunek: 412 EUR. Te same dashboardy, te same insighty, 10× taniej.
To typowy wynik, kiedy audyt kosztów BigQuery znajduje low-hanging fruit. Rzadko to problem architektury. Prawie zawsze to konkretne zapytania, które ktoś raz napisał i zapomniał.
Myślisz, że Twój rachunek BigQuery ma podobny tłuszcz do wycięcia? Napisz do mnie po audyt kosztów, przeglądam Twój billing, Twoje 20 najdroższych zapytań i Twoje scheduled jobs, a potem wręczam Ci priorytetową listę fixów. Bez długich engagementów, bez wymogu retainer.
Ustawianie alertów budżetowych i limitów zapytań
Dwa zabezpieczenia, które każdy setup BigQuery powinien mieć od pierwszego dnia.
1. Google Cloud Billing Budget + alerty
W Google Cloud Console: Billing > Budgets & alerts > Create budget. Ustaw kwotę (np. 100 EUR/mc) i alert na 50%, 90% i 100%. Maile idą do Twoich billing admins, kiedy progi są osiągnięte.
To Twoja siatka bezpieczeństwa. Runaway query o 3 w nocy uderzy w Twojego maila zanim uderzy w biurko Twojego CFO.
2. Limit bytes billed per zapytanie
BigQuery Studio: Settings > Custom quota > Per-query. Ustaw maksymalne bytes billed per zapytanie (np. 100 GB). Dowolne zapytanie, które zeskanowałoby więcej niż limit, pada natychmiast zamiast uruchamiać się i naliczać opłatę.
Dla workloadów GA4 Export 100 GB to rozsądny sufit, legitimatne zapytania analityczne zwykle skanują pod 50 GB. Wszystko powyżej to błąd.
3. Per-user project quota (zaawansowane)
Dla wspólnych projektów, gdzie wielu analityków pyta niezależnie, ustaw per-user quotas, żeby zapobiec temu, że złe zapytanie jednego analityka zje budżet wszystkich. Settings > Quotas > Query usage per day, per user.
On-demand vs reserved slots: kiedy przełączyć
Default BigQuery używa cennika on-demand (5 USD za TB). Kiedy Twój miesięczny rachunek ustabilizuje się w zakresie 2 000-3 000 USD/mc, rozważ przełączenie na capacity-based pricing z Editions (Standard/Enterprise/Enterprise Plus).
Cennik Editions:
- Standard: 0,04 USD za slot-godzinę (używaną)
- Enterprise: 0,06 USD za slot-godzinę
- Commitujesz się do baseline liczby slotów, płacisz za auto-scaling powyżej
Break-even: zapytania on-demand na 5 USD/TB tłumaczą się z grubsza na 1 TB per 40 slot-godzin pod Standard Edition. Jeśli skanujesz 2 TB dziennie, zarezerwowane 100 slotów w Standard Edition kosztuje 24 × 0,04 × 100 = 96 USD/dzień, versus 2 × 5 = 10 USD/dzień on-demand, więc on-demand wygrywa dla umiarkowanych wolumenów.
Punkt break-even siedzi typowo w okolicach 30-50 TB/mc zapytań. Większość mid-market zespołów nigdy tego nie osiąga.
Zasada kciuka: zostań na on-demand, aż Twój rachunek BigQuery przekroczy 2 500 USD/mc konsekwentnie. Poniżej tego progu optymalizacja zapytań oszczędza więcej niż przełączanie modeli cenowych.
Mini-historia: niespodzianka ze streaming inserts
Kuba, data engineer w europejskim SaaS, przejął pipeline BigQuery w lutym 2025, który ingestował eventy userów z kolejki Kafki przez streaming inserts. 50 milionów eventów dziennie. Miesięczny rachunek BigQuery: 890 EUR, z czego 420 EUR to były opłaty streaming inserts.
Wymóg biznesowy nie był faktycznie real-time. Eventy były odpytywane przez dashboardy aktualizowane co godzinę. Streaming był użyty, bo ktokolwiek zbudował pipeline dwa lata wcześniej "potrzebował real-time dla funkcji, która została descope'owana".
Fix: zamień streaming inserts na batch inserts co 15 minut. Trochę bardziej złożony kod (logika batchingu), ale w całości w Pythonie, bez dodatkowej infrastruktury.
Miesięczny koszt streaming po przełączeniu: 0 EUR. Całkowity rachunek BigQuery spadł do 470 EUR. Świeżość danych dla dashboardów była niezmieniona, bo odświeżały się godzinnie i tak.
Streaming inserts to właściwe narzędzie, jeśli naprawdę potrzebujesz sub-minute freshness danych. Jeśli nie, batchuj i oszczędź 47% rachunku.
Monitoring kosztów: trzy zapytania do uruchomienia
Możesz audytować własne koszty BigQuery bez narzędzi third-party. Uruchom te przeciwko widokom INFORMATION_SCHEMA.
Top 20 najdroższych zapytań (ostatnie 30 dni)
SELECT
user_email,
query,
total_bytes_billed / POWER(10, 12) * 5 AS cost_usd,
total_bytes_billed / POWER(10, 9) AS gb_scanned,
total_slot_ms / 1000 AS slot_seconds,
creation_time
FROM region-eu.INFORMATION_SCHEMA. JOBS_BY_PROJECT
WHERE creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
AND job_type = 'QUERY'
AND statement_type!= 'SCRIPT'
ORDER BY total_bytes_billed DESC
LIMIT 20
Samo to identyfikuje zapytania zjadające Twój budżet. Zwykle 3-5 zapytań odpowiada za 80% kosztu.
Koszt zapytań per user
SELECT
user_email,
ROUND(SUM(total_bytes_billed) / POWER(10, 12) * 5, 2) AS cost_usd,
COUNT(*) AS queries
FROM region-eu.INFORMATION_SCHEMA. JOBS_BY_PROJECT
WHERE creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
AND job_type = 'QUERY'
GROUP BY user_email
ORDER BY cost_usd DESC
Przydatne do ustalania, czy koszty biorą się z dashboardów (service account user), scheduled queries (inny service account), czy ludzkich analityków.
Trend kosztów dziennych
SELECT
DATE(creation_time) AS day,
ROUND(SUM(total_bytes_billed) / POWER(10, 12) * 5, 2) AS cost_usd
FROM region-eu.INFORMATION_SCHEMA. JOBS_BY_PROJECT
WHERE creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 60 DAY)
AND job_type = 'QUERY'
GROUP BY day
ORDER BY day DESC
Uruchamiaj to co tydzień. Spiki to sygnał, zbadaj dowolny dzień, który jest 2× powyżej 30-dniowej mediany.
Chcesz te zapytania ustawione w dashboardzie Looker Studio, który alertuje na spiki? Zobacz moje usługi, wdrożenia monitoringu BigQuery.
Najczęściej zadawane pytania
Dlaczego mój rachunek BigQuery jest tak wysoki?
W 95% przypadków odpowiedź to jeden z pięciu błędów: scheduled queries przebudowujące pełne agregaty codziennie, zapytania na GA4 events_ bez filtra _TABLE_SUFFIX, SELECT na szerokich schemach, streaming inserts użyte, gdy batch by działał, albo dashboardy z zbyt częstymi interwałami odświeżania rozbijające cache zapytań. Uruchom zapytania INFORMATION_SCHEMA z tego poradnika, żeby zidentyfikować, do której kategorii pasuje Twój rachunek.
Ile kosztuje typowy GA4 Export na BigQuery?
Dla mid-market europejskiego e-commerce z 100 000 sesji dziennie: 5-15 USD/mc w storage, 10-40 USD/mc w zapytaniach, jeśli dashboardy są wydajne, i 0 USD, jeśli trzymasz się batch exports. Typowy rachunek: 15-50 USD/mc łącznie. Rachunki powyżej 200 USD/mc prawie zawsze mają naprawialne nieefektywności.
Czy BigQuery cache'uje zapytania i czy cache jest darmowy?
Tak. BigQuery automatycznie cache'uje wyniki zapytań na 24 godziny. Cache hits nie liczą się do billingu. Cache jest per-query-text, więc dowolna zmiana (w tym whitespace) unieważnia. Dla dashboardów z identycznymi zapytaniami uruchamianymi wielokrotnie dziennie cache dostarcza 90%+ żądań za darmo.
Kiedy powinienem przełączyć z on-demand na reserved slots?
Kiedy Twój miesięczny rachunek BigQuery przekracza 2 500 USD konsekwentnie. Poniżej tego progu optymalizacja zapytań z partition filtering i wyborem konkretnych kolumn oszczędza więcej niż przełączanie modeli cenowych. Reserved slots opłacają się, kiedy masz utrzymane wysokie wolumeny zapytań, typowo 30+ TB/mc.
Jak ustawić limit budżetu na BigQuery?
Dwa sposoby: Google Cloud Billing > Budgets & alerts dla notyfikacji mailowych, i BigQuery Settings > Custom quota dla twardego sufitu na bytes billed per zapytanie. Ustaw alert billingowy na 50% oczekiwanego miesięcznego wydatku, a quota per-query na 10× Twojego typowego największego legitimatnego zapytania. Te dwa razem łapią 99% runaway cost events.
Czy SELECT * naprawdę kosztuje więcej niż SELECT lista_kolumn?
Tak, znacząco. BigQuery jest kolumnowe. SELECT skanuje każdą kolumnę dla każdego zwracanego wiersza. Na schema GA4 Export z zagnieżdżonymi event_params i user_properties, SELECT typowo skanuje 10-50× więcej danych niż SELECT event_name, user_pseudo_id. Różnica na tabeli 100 GB to skan 100 GB (koszt: 0,50 USD) vs 2-5 GB (koszt: 0,01-0,03 USD).
Podsumowanie
BigQuery jest tanie dla zespołów, które piszą wydajny SQL, i drogie dla zespołów, które nie piszą. Sam cennik (5 USD za TB query, 0,02 USD za GB/miesiąc storage) jest fair, a free tier pokrywa małe workloady całkowicie.
Jeśli Twój rachunek Cię zaskakuje, przyczyna prawie zawsze siedzi w Twoich zapytaniach, nie w cenniku BigQuery. Uruchom zapytania INFORMATION_SCHEMA powyżej, znajdź swoje top 20 najdroższych jobs i zastosuj siedem optymalizacji do tych konkretnych zapytań. Większość zespołów odzyskuje 60-90% rachunku w jedno popołudnie.
Ustaw alerty billingowe i limity bytes-billed per zapytanie od pierwszego dnia. Koszt 15 minut setupu to jeden miesiąc Twojego ostatecznego rachunku BigQuery, zwrócony pierwszy raz, gdy coś pójdzie źle.
Chcesz, żebym zaudytował Twój rachunek BigQuery i zidentyfikował, gdzie przecieka? Napisz do mnie po zescope'owaną ocenę kosztów. Analizuję Twoje top queries, scheduled jobs i dashboardy, a potem wręczam Ci priorytetową listę fixów z oczekiwanymi oszczędnościami w EUR. Bez długich engagementów, tylko optymalizacja, którą możesz wdrożyć w tym tygodniu.
Chcesz, żebym zaudytował Twój rachunek BigQuery?
Analizuję Twoje top queries, scheduled jobs i dashboardy, a potem wręczam priorytetową listę fixów z oczekiwanymi oszczędnościami w EUR. Bez długich engagementów.
Zobacz moje uslugiPotrzebujesz pomocy? Napisz do mnie
Masz pytanie dotyczące analityki? Wypełnij formularz, zwykle odpowiadam w ciągu 24 godzin.