Dane i infrastruktura

BigQuery w szkołach: kompletny przewodnik po wdrożeniu, obsłudze i możliwościach

Analiza systemowa
BigQuery w szkołach: kompletny przewodnik po wdrożeniu, obsłudze i możliwościach

Od silosów danych do wiedzy, na której można działać — dla adminów IT, dyrektorów i nauczycieli-innowatorów


Dlaczego szkoła potrzebuje hurtowni danych

Większość szkół zbiera dane od lat — frekwencję, oceny, wyniki ankiet, logi bezpieczeństwa, aktywność na platformach edukacyjnych. Problemem nie jest brak danych. Problemem jest to, że leżą one w osobnych, szczelnie zamkniętych pojemnikach: jeden system tu, drugi tam, papierowy dziennik gdzie indziej, czujnik jakości powietrza w trzeciej zakładce przeglądarki. Nauczyciel, który chce zrozumieć, czy uczeń ma problem nie tylko z matematyką, ale też z frekwencją na środowych lekcjach i zaangażowaniem na Classroomie — musi ręcznie przeklikać się przez trzy systemy.

BigQuery jest odpowiedzią na ten problem. To w pełni zarządzana, bezserwerowa hurtownia danych Google Cloud Platform, zdolna analizować miliardy wierszy w kilka sekund. Dla państwowej szkoły brzmi to jak strzelanie z armaty do muchy — ale diabeł tkwi w szczegółach. BigQuery działa świetnie nawet przy kilku tysiącach wierszy, jest darmowy do 10 GB przechowywanych danych i 1 TB zapytań miesięcznie, natywnie integruje się z Google Workspace i nie wymaga bycia programistą, żeby go obsługiwać.

Ten artykuł nie jest dla osób, które chcą się dowiedzieć, czym jest chmura. Jest dla tych, którzy zarządzają cyfrową infrastrukturą szkoły i chcą konkretnych odpowiedzi: jak to skonfigurować, jak podłączyć dane z Classroom, co zrobić z logami bezpieczeństwa i jak zaprezentować to wszystko dyrektorowi w czytelnym dashboardzie.

Dla kogo jest ten artykuł: Dla admina Workspace, który chce wiedzieć, jak to postawić. Dla dyrektora, który chce zrozumieć, co z tego ma. Dla nauczyciela-innowatora, który chce budować własne analizy. Każda sekcja zaczyna się od podstaw i wchodzi głębiej — czytaj tak daleko, jak potrzebujesz.


Architektura: jak dane trafiają do BigQuery

Zanim zabierzemy się za konfigurację, warto zrozumieć przepływ danych. W typowym szkolnym środowisku Google Workspace źródeł jest zwykle kilka:

  • Google Classroom API — aktywność uczniów, zadania, terminy, oceny, komentarze
  • Google Workspace Admin SDK — logi bezpieczeństwa, logowania, akcje w Workspace
  • Google Forms / Sheets — ankiety, zapisy do kół, rejestracje na wydarzenia
  • Systemy zewnętrzne — dzienniki elektroniczne (Librus, Vulcan), czujniki IoT (Airly), systemy biblioteczne

Dwa modele wdrożenia

W praktyce szkoły korzystają z jednego z dwóch podejść do zasilania BigQuery:

Model 1: Apps Script jako warstwa ETL

Najprostsze i najbardziej dostępne podejście dla szkół korzystających z Google Workspace. Apps Script pobiera dane z Classroom API lub innych źródeł Google i zapisuje je do BigQuery przez wbudowaną usługę BigQueryApp.

// Example: exporting assignment results to BigQuery
function exportAssignmentsToBQ() {
  const projectId = "your-gcp-project";
  const datasetId = "classroom_data";
  const tableId   = "assignments";

  const courses = Classroom.Courses.list().courses || [];
  const rows = [];

  courses.forEach(course => {
    const works = Classroom.Courses.CourseWork.list(course.id).courseWork || [];
    works.forEach(work => {
      const subs = Classroom.Courses.CourseWork
        .StudentSubmissions.list(course.id, work.id).studentSubmissions || [];
      subs.forEach(sub => {
        rows.push({ insertId: sub.id, json: {
          course_id:    course.id,
          course_name:  course.name,
          work_id:      work.id,
          work_title:   work.title,
          student_id:   sub.userId,   // pseudonymise in production!
          state:        sub.state,
          late:         sub.late || false,
          grade:        sub.assignedGrade || null,
          timestamp:    new Date().toISOString()
        }});
      });
    });
  });

  if (rows.length === 0) return;

  BigQuery.Tabledata.insertAll(
    { rows }, projectId, datasetId, tableId
  );
}

Uwaga o RODO: W środowisku produkcyjnym identyfikatory uczniów muszą być pseudonimizowane — zamiast adresu e-mail czy nazwiska użyj UUID wygenerowanego raz i przechowywanego w osobnej tabeli mapującej. Dzięki temu analityk widzi wzorce, ale bez odpowiednich uprawnień nie ma dostępu do danych osobowych.

Model 2: Bezpośrednia integracja przez Google Cloud

Wariant bardziej zaawansowany, w którym dane wpływają do BigQuery kilkoma kanałami jednocześnie: Pub/Sub dla zdarzeń w czasie rzeczywistym, Cloud Functions lub Cloud Run do przetwarzania danych z zewnętrznych API, oraz Data Transfer Service dla gotowych konektorów (np. Google Analytics, YouTube Analytics).

# Pipeline schema for Airly sensor data (Python / Cloud Function)

def airly_to_bq(request):
    import requests, google.cloud.bigquery as bq
    from datetime import datetime

    API_KEY      = "your_airly_key"
    INSTALLATION = "12345"
    PROJECT      = "your-gcp-project"
    DATASET      = "environmental"
    TABLE        = "airly_readings"

    r = requests.get(
        f"https://airapi.airly.eu/v2/measurements/installation"
        f"?installationId={INSTALLATION}",
        headers={"apikey": API_KEY}
    ).json()

    current = r["current"]["values"]
    row = {
        "timestamp":   datetime.utcnow().isoformat(),
        "pm25":        next((v["value"] for v in current if v["name"]=="PM2.5"), None),
        "pm10":        next((v["value"] for v in current if v["name"]=="PM10"),  None),
        "temperature": next((v["value"] for v in current if v["name"]=="TEMPERATURE"), None),
    }

    client = bq.Client(project=PROJECT)
    table  = client.get_table(f"{PROJECT}.{DATASET}.{TABLE}")
    client.insert_rows_json(table, [row])
    return "ok"

Konfiguracja krok po kroku

1. Projekt Google Cloud Platform

BigQuery żyje wewnątrz projektu GCP. Jeśli korzystasz z Google Workspace for Education, twoja szkoła ma już dostęp do GCP w ramach tej samej organizacji Google. Polecam utworzyć dedykowany projekt — np. school-analytics-2026 — osobny od innych zasobów szkoły. Dzięki temu rozliczenia, uprawnienia i ślady audytowe pozostają czyste.

  1. Wejdź na console.cloud.google.com
  2. Utwórz nowy projekt: Resource Manager → Create Project
  3. Wybierz organizację szkoły (ważne dla uprawnień!)
  4. Włącz BigQuery API: APIs & Services → Enable APIs → wyszukaj „BigQuery”
  5. Włącz Classroom API i Admin SDK API, jeśli używasz Apps Script

Lokalizacja danych: Dla szkół w UE wybierz europe-central2 (Warszawa) lub europe-west1 (Belgia). Dane uczniów przetwarzane na gruncie RODO nie powinny opuszczać UE. Lokalizację ustawia się raz, przy tworzeniu zbioru danych — później nie da się jej zmienić.

2. Schemat bazy — zbiory danych i tabele

Zbiór danych (dataset) to odpowiednik schematu w tradycyjnej bazie — pojemnik na tabele. Polecam osobne zbiory dla różnych domen:

Zbiór danychZawartość
classroom_dataAktywność Google Classroom: kursy, zadania, przesłane prace, oceny
workspace_auditLogi bezpieczeństwa: logowania, dostęp do Drive, akcje admina
environmentalDane z czujników: Airly, temperatura, wilgotność
journal_dataImport z dziennika elektronicznego: frekwencja, oceny, uwagi
analyticsZagregowane widoki i tabele: fundament dashboardów

Tabele w BigQuery mają schemat — jawnie zdefiniowane kolumny z typami. Oto przykładowy schemat tabeli aktywności uczniów:

// JSON schema for student_activity table
[
  { "name": "event_id",     "type": "STRING",    "mode": "REQUIRED" },
  { "name": "course_id",    "type": "STRING",    "mode": "REQUIRED" },
  { "name": "course_name",  "type": "STRING",    "mode": "NULLABLE" },
  { "name": "student_uuid", "type": "STRING",    "mode": "REQUIRED" },
  { "name": "event_type",   "type": "STRING",    "mode": "REQUIRED" },
  { "name": "work_id",      "type": "STRING",    "mode": "NULLABLE" },
  { "name": "work_title",   "type": "STRING",    "mode": "NULLABLE" },
  { "name": "state",        "type": "STRING",    "mode": "NULLABLE" },
  { "name": "late",         "type": "BOOLEAN",   "mode": "NULLABLE" },
  { "name": "grade",        "type": "FLOAT64",   "mode": "NULLABLE" },
  { "name": "max_grade",    "type": "FLOAT64",   "mode": "NULLABLE" },
  { "name": "timestamp",    "type": "TIMESTAMP", "mode": "REQUIRED" },
  { "name": "school_year",  "type": "STRING",    "mode": "NULLABLE" }
]

3. Uprawnienia i bezpieczeństwo

Zarządzanie uprawnieniami w BigQuery opiera się na rolach IAM (Identity and Access Management). W środowisku szkolnym stosuj zasadę minimalnych uprawnień:

RolaKiedy przydzielać
roles/bigquery.dataViewerNauczyciel przeglądający własne dane — tylko odczyt
roles/bigquery.dataEditorApps Script zapisujący dane — odczyt i zapis do tabel
roles/bigquery.jobUserKonto techniczne uruchamiające zapytania (np. Looker Studio)
roles/bigquery.adminAdmin IT — pełna kontrola. Przydzielaj z rozwagą
roles/bigquery.dataOwnerWłaściciel zbioru danych — może nadawać uprawnienia w swoim zakresie

Konto usługi dla Apps Script czy Cloud Functions nigdy nie powinno mieć uprawnień admina. Nadaj mu roles/bigquery.dataEditor na konkretnym zbiorze danych, a nie na całym projekcie.


SQL w szkolnej praktyce

BigQuery używa Google Standard SQL — zgodnego z ANSI SQL. Jeśli kiedykolwiek pisałeś zapytania w MySQL, PostgreSQL czy choćby Accessie, opanujesz go w kilka godzin. Poniżej przykłady, które przydają się w szkole wprost.

Zapytanie 1: Uczniowie zagrożeni oceną niedostateczną

Znajdź uczniów, którzy w ostatnich 30 dniach oddali mniej niż 50% zadań, mają co najmniej 3 spóźnione prace, a ich średnia ważona spadła poniżej progu zaliczenia:

SELECT
  student_uuid,
  COUNT(*) AS total_works,
  COUNTIF(state = "TURNED_IN" OR state = "RETURNED") AS submitted,
  ROUND(COUNTIF(state = "TURNED_IN" OR state = "RETURNED")
        / COUNT(*) * 100, 1) AS submission_rate_pct,
  COUNTIF(late = TRUE) AS late_count,
  ROUND(AVG(grade / NULLIF(max_grade, 0)) * 100, 1) AS weighted_avg_pct
FROM
  `project.classroom_data.student_activity`
WHERE
  timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
  AND max_grade IS NOT NULL
GROUP BY
  student_uuid
HAVING
  submission_rate_pct < 50
  OR late_count >= 3
  OR weighted_avg_pct < 50
ORDER BY
  submission_rate_pct ASC
LIMIT 50;

Zapytanie 2: Korelacja między frekwencją a wynikami

Czy uczniowie z ponad 15% absencji mają statystycznie niższe oceny? Zapytanie łączy dane z dziennika z danymi z Classroom:

WITH attendance AS (
  SELECT
    student_uuid,
    ROUND(COUNTIF(status = "ABSENT") / COUNT(*) * 100, 1) AS absence_pct
  FROM `project.journal_data.attendance`
  WHERE school_year = "2025/2026"
  GROUP BY student_uuid
),
grades AS (
  SELECT
    student_uuid,
    ROUND(AVG(grade / NULLIF(max_grade, 0)) * 100, 1) AS avg_score_pct
  FROM `project.classroom_data.student_activity`
  WHERE grade IS NOT NULL AND max_grade > 0
  GROUP BY student_uuid
)
SELECT
  a.student_uuid,
  a.absence_pct,
  g.avg_score_pct,
  CASE
    WHEN a.absence_pct < 5  THEN "low (<5%)"
    WHEN a.absence_pct < 15 THEN "moderate (5–15%)"
    ELSE "high (>15%)"
  END AS absence_group
FROM attendance a
JOIN grades g USING (student_uuid)
ORDER BY a.absence_pct DESC;

Zapytanie 3: Analiza bezpieczeństwa — podejrzane logowania

Ze zbioru workspace_audit wyciągnij konta, które w ciągu tygodnia logowały się z więcej niż 3 różnych krajów — klasyczny sygnał przejętego konta:

SELECT
  actor_email,
  COUNT(DISTINCT country_code) AS unique_countries,
  ARRAY_AGG(DISTINCT country_code) AS countries,
  COUNT(*) AS total_logins,
  MIN(event_time) AS first_login,
  MAX(event_time) AS last_login
FROM
  `project.workspace_audit.login_events`
WHERE
  event_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
  AND event_type = "login"
  AND result = "SUCCESS"
GROUP BY
  actor_email
HAVING
  unique_countries >= 3
ORDER BY
  unique_countries DESC, total_logins DESC;

Wskazówka: Uruchamiaj to zapytanie codziennie przez Cloud Scheduler i wysyłaj wyniki mailem do admina przez Apps Script. Nie musisz siedzieć i wpatrywać się w dashboard — pozwól, żeby dane same do ciebie przychodziły.

Zapytanie 4: Jakość powietrza a aktywność uczniów

Czy w dni z wysokim PM2.5 uczniowie oddają mniej zadań? Zapytanie łączy dane z czujnika Airly z danymi z Classroom:

WITH daily_air AS (
  SELECT
    DATE(timestamp) AS day,
    ROUND(AVG(pm25), 1) AS avg_pm25,
    CASE
      WHEN AVG(pm25) < 25  THEN "good"
      WHEN AVG(pm25) < 50  THEN "moderate"
      ELSE "poor"
    END AS air_quality
  FROM `project.environmental.airly_readings`
  WHERE timestamp >= "2025-09-01"
  GROUP BY day
),
daily_activity AS (
  SELECT
    DATE(timestamp) AS day,
    COUNT(*) AS submissions
  FROM `project.classroom_data.student_activity`
  WHERE state = "TURNED_IN"
  GROUP BY day
)
SELECT
  a.day,
  a.avg_pm25,
  a.air_quality,
  COALESCE(s.submissions, 0) AS submissions
FROM daily_air a
LEFT JOIN daily_activity s USING (day)
ORDER BY a.day;

Looker Studio: od danych do decyzji

BigQuery bez warstwy wizualizacji to silnik bez kierownicy. Looker Studio (dawniej Data Studio) to darmowe narzędzie Google do budowania interaktywnych dashboardów — a jego natywna integracja z BigQuery to jedna z największych zalet całego stacku.

Podłączenie BigQuery do Looker Studio

  1. W Looker Studio utwórz nowe źródło danych
  2. Wybierz konektor BigQuery
  3. Zaloguj się na konto z rolą roles/bigquery.jobUser
  4. Wybierz projekt, zbiór danych i tabelę (lub widok)
  5. Skonfiguruj odświeżanie danych (cache od 1h do 12h)

Polecam używać w BigQuery widoków (Views) jako źródeł dla Looker Studio — a nie tabel bezpośrednio. Widok to zapisane zapytanie SQL, które: ukrywa surowe dane, stosuje pseudonimizację, odfiltrowuje zbędne kolumny i pozwala zmieniać logikę bez modyfikowania raportu.

-- Example: a teacher-safe view
CREATE OR REPLACE VIEW `project.analytics.teacher_dashboard_v` AS
SELECT
  course_name,
  work_title,
  state,
  late,
  ROUND(grade / NULLIF(max_grade, 0) * 100, 0) AS score_pct,
  FORMAT_TIMESTAMP("%Y-%m-%d", timestamp) AS date
FROM `project.classroom_data.student_activity`
-- student_uuid intentionally omitted — teacher sees trends, not individuals
WHERE school_year = "2025/2026";

Rekomendowane dashboardy dla szkół

DashboardZawartość
Panel nauczycielaAktywność w kursie, odsetek oddanych prac, rozkład ocen, tygodniowy trend
Panel wychowawcyAbsencja klasy, uczniowie zagrożeni, porównanie z poprzednim rokiem
Panel dyrektoraKPI na poziomie szkoły, trendy roczne, benchmarki między klasami
Panel admina ITLogi bezpieczeństwa, podejrzane konta, status synchronizacji danych
Panel środowiskowyJakość powietrza, korelacje z frekwencją, trendy sezonowe

Trik z Row-Level Security: Looker Studio nie ma wbudowanego RLS, ale możesz je zasymulować przez BigQuery. Utwórz widok, który filtruje dane na podstawie funkcji SESSION_USER() — czyli adresu e-mail zalogowanego użytkownika. Każdy nauczyciel widzi tylko własne kursy, a dyrektor widzi wszystko.


Studia przypadków: BigQuery w akcji

Przypadek 1: Szkoła im. Leonardo Piwoni, Szczecin

W ramach szkolnego projektu cyfryzacji zbudowano pipeline: Google Classroom API → Apps Script (ETL) → BigQuery → Looker Studio. Nocny wyzwalacz (23:00) pobiera aktywność ze wszystkich kursów i zapisuje ją do BigQuery. Całkowity czas wykonania: około 4 minuty dla 750 uczniów i 60 nauczycieli.

Kluczowy wniosek po pierwszym roku: dane ujawniają wzorce niewidoczne w codziennym kontakcie. Klasy, które wydawały się aktywne, miały wysoki odsetek spóźnionych prac skupionych tuż przed terminem — sygnał uczenia się na ostatnią chwilę. Klasy sprawiające wrażenie cichszych miały bardziej równomierny rozkład pracy w ciągu tygodnia.

Mierzalny efekt: Czas, jakiego wychowawca potrzebował na zidentyfikowanie uczniów zagrożonych, spadł z około 45 minut (przeklikiwanie się przez systemy) do 2 minut (otwarcie dashboardu). Interwencja pedagogiczna stała się reakcją na dane na żywo, a nie działaniem po fakcie.

Przypadek 2: Monitoring bezpieczeństwa Workspace

Szkolny admin IT eksportuje logi z Google Workspace Admin SDK do BigQuery za pomocą automatycznego eksportu (BigQuery Export w ustawieniach Admin Console — dostępny od Workspace Business Starter). Logi wpływają do BigQuery automatycznie, bez pisania ani linijki kodu.

Na tych danych można zbudować alerty dla: logowań z nowych urządzeń poza szkołą, masowego pobierania plików z Drive, zmian uprawnień przez dowolne konto inne niż admin oraz prób logowania do usług wyłączonych dla szkoły.

Przypadek 3: Integracja z dziennikiem elektronicznym

Librus i Vulcan nie mają oficjalnych API dla szkół na standardowych planach. Najskuteczniejsze podejście: codzienny eksport CSV z dziennika (funkcja dostępna w obu systemach), wgranie na Google Drive przez nauczyciela lub sekretariat, automatyczne przetworzenie przez Apps Script do BigQuery. Cały pipeline jest zautomatyzowany przez wyzwalacz Drive — każdy nowy plik CSV w wyznaczonym folderze uruchamia funkcję importu.

// Drive folder trigger — automatic CSV import
function setupDriveTrigger() {
  const folderId = "YOUR_EXPORTS_FOLDER_ID";
  ScriptApp.newTrigger("onNewCsvInDrive")
    .forSpreadsheet(SpreadsheetApp.create("trigger-helper"))
    .onChange()
    .create();
}

function onNewCsvInDrive() {
  const folder = DriveApp.getFolderById("YOUR_EXPORTS_FOLDER_ID");
  const files  = folder.getFilesByType("text/csv");
  while (files.hasNext()) {
    const file = files.next();
    if (!file.getName().startsWith("processed_")) {
      importCsvToBigQuery(file);
      file.setName("processed_" + file.getName());
    }
  }
}

Przypadek 4: Czujnik jakości powietrza Airly

Szkolny projekt „Zielona Tarcza” łączy monitoring jakości powietrza z danymi edukacyjnymi. Czujnik Airly mierzy co godzinę PM2.5, PM10 i temperaturę. Cloud Function (darmowy poziom: 2 mln wywołań miesięcznie) pobiera dane z Airly API i zapisuje je do BigQuery.

Po pół roku zbierania danych szkoła ma materiał na lekcje przyrody, fizyki i statystyki — a Looker Studio pokazuje dzieciom w czasie rzeczywistym, czym oddychają. To nie jest ozdoba: uczniowie sami wyszli z propozycją przygotowywania regularnych raportów dla Rady Rodziców.


Koszty i darmowy poziom

Jedno z najczęstszych pytań brzmi: „ile to kosztuje?”. Uczciwa odpowiedź: dla typowej szkoły — prawie nic albo zupełnie nic.

KomponentDarmowy poziom
Przechowywanie danychPierwsze 10 GB miesięcznie za darmo. Rok danych szkolnych (750 uczniów) to zwykle 2–5 GB.
ZapytaniaPierwszy 1 TB przetworzonych danych miesięcznie za darmo. Typowy szkolny dashboard zużywa około 1–10 GB/miesiąc.
Streaming insertJedyny niezerowy koszt dla małych szkół: 0,01 USD za 200 MB. Przy 750 uczniach około 1–3 USD/miesiąc. Da się tego uniknąć, korzystając z trybu batch.
BigQuery MLPierwsze 10 GB zapytań ML miesięcznie za darmo.
Looker StudioZa darmo, bez limitów.

Jak uniknąć niespodzianek: Ustaw alert budżetowy w GCP Console (Billing → Budgets & Alerts). Próg 5 USD/miesiąc z alertem mailowym daje pełny spokój ducha. W ciągu roku prowadzenia szkolnego pipeline’u rachunki mieszczą się zwykle między 0 a 2 USD/miesiąc.

BigQuery a alternatywy dla szkół

RozwiązanieOcena dla szkół
Google SheetsLimit 5 mln komórek, brak SQL, brak skalowalności. Dobre do raportów, nie do analizy.
Looker Studio bez BQOgraniczone możliwości transformacji. Brak złożonych zapytań.
PostgreSQL (VPS)Pełna kontrola, ale wymaga administracji serwerem, backupów, zabezpieczeń — poważny, stały wysiłek.
BigQueryBezserwerowy, darmowy w szkolnej skali, natywna integracja z Workspace, SQL, ML, skalowalność.

Plan wdrożenia: od zera do działającego systemu

Realistyczny harmonogram dla jednej osoby (admin IT + determinacja) bez wsparcia z zewnątrz:

FazaZadania
Tydzień 1Projekt GCP, zbiory danych, pierwsze tabele. Próbny eksport z jednego kursu Classroom do BQ. Weryfikacja schematu.
Tydzień 2Pełny pipeline w Apps Script. Pseudonimizacja UUID. Pierwszy widok w Looker Studio.
Tydzień 3Nocny wyzwalacz. Testy na danych z całego roku. Wykrywanie i naprawa przypadków brzegowych (brakujące oceny, usunięte kursy).
Tydzień 4Dashboard nauczyciela. Pilotaż z 2–3 chętnymi wychowawcami. Zbieranie informacji zwrotnej.
Miesiąc 2Panel dyrektora. Integracja z dziennikiem lub czujnikiem. Dokumentacja. Szkolenie zastępczego admina.
Miesiąc 3+Analityka predykcyjna (BigQuery ML). Automatyczne alerty. Rozszerzenie o kolejne źródła danych.

Typowe pułapki

  • Niezgodność schematu: Apps Script zwraca null tam, gdzie BigQuery oczekuje STRING. Zawsze waliduj typy przed insertAll.
  • Duplikaty z wyzwalaczy: Jeśli wyzwalacz odpali się dwa razy, dostajesz podwójne wpisy. Użyj insertId jako deduplikatora — BigQuery automatycznie ignoruje duplikaty przez około 1 minutę.
  • getActiveSpreadsheet() w wyzwalaczu: W wyzwalaczu czasowym ta funkcja zwraca null. Zawsze używaj openById() z jawnym ID arkusza.
  • Brak obsługi błędów: Jeśli kurs jest zarchiwizowany lub usunięty, Classroom API rzuca wyjątek. Owijaj pętle w try/catch i loguj błędy do osobnej tabeli w BQ.
  • Koszty zapytań w Looker Studio: Domyślnie Looker Studio odpytuje BQ przy każdym odświeżeniu strony. Włącz cache (minimum 1h) — dla danych szkolnych odświeżanie co 4–12h w zupełności wystarcza.

BigQuery ML: analityka predykcyjna bez Pythona

BigQuery ML pozwala trenować modele uczenia maszynowego bezpośrednio w SQL, bez eksportowania danych do zewnętrznych narzędzi. Dla szkół najciekawsze zastosowania to: przewidywanie ryzyka niepowodzenia (klasyfikacja) i przewidywanie absencji (regresja).

Model predykcji ryzyka

-- Creating a classification model (logistic regression)
CREATE OR REPLACE MODEL `project.analytics.risk_model`
OPTIONS(
  model_type = "logistic_reg",
  input_label_cols = ["at_risk"],
  l2_reg = 0.1
) AS
SELECT
  submission_rate,
  late_rate,
  avg_score,
  absence_pct,
  IF(avg_score < 0.5 OR absence_pct > 20, TRUE, FALSE) AS at_risk
FROM `project.analytics.student_features_v`;

-- Prediction for the current period
SELECT
  student_uuid,
  predicted_at_risk,
  predicted_at_risk_probs[OFFSET(1)].prob AS risk_probability
FROM ML.PREDICT(
  MODEL `project.analytics.risk_model`,
  (SELECT * FROM `project.analytics.student_features_current_v`)
)
ORDER BY risk_probability DESC
LIMIT 20;

Ważna perspektywa: Modele predykcyjne w szkole to narzędzia wsparcia, a nie wyroki. Wynik modelu powinien trafiać do wychowawcy jako „warto porozmawiać z tym uczniem” — a nie jako etykieta w systemie. Przy każdym zautomatyzowanym profilowaniu uczniów RODO wymaga przeprowadzenia DPIA (oceny skutków dla ochrony danych).


Podsumowanie

BigQuery to nie rozwiązanie w poszukiwaniu problemu. To infrastruktura, która pozwala szkole zadawać pytania o własne dane — i dostawać odpowiedzi szybciej niż w cotygodniowym cyklu raportowania.

Trzy rzeczy warte zapamiętania:

  1. Zacznij od małego. Jeden zbiór danych, jeden Apps Script, jeden dashboard dla jednego wychowawcy. Sukces w małej skali to najlepszy argument dla dyrektora.
  2. Dane wymagają zaufania. Techniczny pipeline to 30% pracy. 70% to ustalenie z nauczycielami, co chcą widzieć, jak interpretować dane i gdzie kończy się narzędzie, a zaczyna rozmowa z uczniem.
  3. RODO to nie zagrożenie. Pseudonimizacja, DPIA, rejestr czynności przetwarzania — to dwie godziny pracy nad dokumentacją, które dają lata spokoju i pokazują, że szkoła działa poważnie.

Pełny kod pipeline’u (Apps Script + schemat BQ + widoki Looker Studio) jest dostępny w repozytorium workspace.edu.pl na GitHubie. Pytania i doświadczenia z własnych wdrożeń mile widziane w komentarzach lub na GEG Poland.