Powrót do strony głównej

Filtry po dacie w Apache Superset: obejścia

Artykuł analizuje architektoniczne ograniczenia filtrowania po dacie w Apache Superset (wersje 3.x–6.x). Opisuje, dlaczego wybór default time column opiera się na leksykografii, jakie ryzyka to stwarza w production i podaje technicznie uzasadnione obejścia dla middle/senior-programistów.

Superset i data: dlaczego filtry łamią logikę biznesową
Advertisement 728x90

Apache Superset: jak obejść ograniczenia filtrów po dacie w wersjach 3.x–6.x

Apache Superset nie umożliwia przypięcia filtra datowego do konkretnej kolumny czasowej na poziomie wykresu — wybór zawsze jest globalny dla zestawu danych i zależy od porządku alfabetycznego nazw pól. To powoduje poważne problemy w środowiskach produkcyjnych: niekontrolowane zmiany logiki biznesowej, konflikty między dashboardami oraz ukryte regresje przy zmianie domyślnej kolumny czasowej. W artykule analizujemy architektoniczne przyczyny, sprawdzone praktyczne obchody oraz techniczne ograniczenia obecnych rozwiązań.

Dlaczego Superset wybiera bot_profile__updated — i dlaczego to niebezpieczne

Superset automatycznie ustala domyślną kolumnę czasową podczas tworzenia zestawu danych, kierując się wyłącznie alfabetycznym porządkiem nazw kolumn typu TIMESTAMP, DATETIME lub DATE. W zestawie danych messages pole bot_profile__updated okazuje się pierwsze w kolejności alfabetycznej wśród bot_profile__updated, ts, created_at i updated_at. Takie zachowanie jest zdefiniowane w pliku superset/datasets/models.py, gdzie metoda get_default_time_column() wykorzystuje sorted([col for col in dataset.columns if col.is_temporal]) bez uwzględnienia semantyki, kontekstu biznesowego ani metadanych.

Kluczowe ryzyko polega na tym, że zmiana domyślnej kolumny czasowej w zestawie danych wpływa na wszystkie wykresy i dashboardy, które z niej korzystają, nawet jeśli logicznie odnoszą się do różnych osi czasowych. Na przykład:

Google AdInline article slot
  • Wykres „Aktywność botów” powinien być filtrowany według ts (moment zdarzenia);
  • Wykres „Aktualizacje profilu” — według bot_profile__updated (moment zmiany entitety);
  • Oba używają tego samego zestawu danych messages.

Jeśli administrator zmieni domyślną kolumnę czasową na ts, drugi wykres zacznie wyświetlać dane na niewłaściwej osi czasowej — bez błędów, bez logów, bez ostrzeżeń. Żółte powiadomienie w interfejsie użytkownika jedynie o tym przypomina, ale nie blokuje operacji.

Filtr kolumny czasowej: funkcjonalny krzyk z systemowymi ograniczeniami

Począwszy od wersji 3.0 Superset wprowadził filtr typu Time Column, który wyświetla rozwijany listę wszystkich kolumn czasowych w zestawie danych i pozwala wybrać jedną. Jednak jego implementacja nie jest rozwiązaniem, a raczej abstrakcją nad istniejącym defektem:

  • Wybrana wartość w filtrze Time Column Filter globalnie przekreśla default_time_column dla wszystkich filtrów datowych na danym dashboardzie;
  • Nie można dodać dwóch niezależnych filtrów datowych (np. „okres zdarzenia” i „okres przetwarzania”) — oba będą korzystać z tej samej wybranej wartości;
  • Filtr nie obsługuje wyrażeń warunkowych (WHERE ts BETWEEN ... AND ... AND updated_at > ...);
  • Nie wpływa na agregacje w zapytaniach SQL, tylko na filtrację przez WHERE.

To prowadzi do wzoru „filtr-proxy”, gdy programiści są zmuszeni duplikować zestawy danych z różnymi default_time_column, aby izolować logikę. Taki podejście narusza zasadę DRY, komplikuje utrzymanie i zwiększa obciążenie metadanych.

Google AdInline article slot

Praktyczne rozwiązania techniczne dla programistów średniego i wysokiego szczebla

Dla stabilnej eksploatacji Superset w produkcji zaleca się następujące podejścia:

  • Tworzenie wirtualnych zestawów danych za pomocą SQL Lab

- Dla każdego unikalnego kontekstu czasowego tworzy się osobny zestaw danych SQL z wyraźnym SELECT ... AS time_dimension FROM ...;

- Nazwa time_dimension jest zapisywana jako jedyna kolumna czasowa, eliminując dwuznaczność;

Google AdInline article slot

- Przykład:

SELECT 
  ts AS time_dimension,
  user_id,
  event_type,
  payload
FROM messages
WHERE ts IS NOT NULL
  • Używanie extra_json do wymuszonej przypięcia

- W edytorze zestawu danych w polu Extra JSON podaje się:

{"default_time_column": "ts"}

- Funkcjonuje to tylko przy istnieniu odpowiedniego pola w columns.extra i wymaga ręcznego aktualizowania przy zmianie schematu;

  • Patchowanie Dataset.get_default_time_column() w niestandardowym obrazie

- Dodanie obsługi anotacji poprzez komentarze w bazie danych (COMMENT ON COLUMN messages.ts IS 'time_dimension:primary');

- Parowanie komentarzy w get_default_time_column();

- Wymaga integracji z CI/CD i testów kompatybilności z nowymi wersjami.

  • Rezygnacja z wbudowanych filtrów na rzecz parametryzowanych wykresów SQL

- Wszystkie filtry czasowe przenoszone są do warunków WHERE wykresu z użyciem {{ filter_values('date_range') }};

- Pozwala to stosować wiele niezależnych filtrów i skomplikowane warunki;

- Minus — traci się wizualizację filtrów w interfejsie dashboarda.

Co jest ważne

  • Superset nie rozróżnia semantycznego znaczenia kolumn czasowych: ts, created_at i updated_at traktowane są jako równorzędne strings do sortowania.
  • Zmiana default_time_column w zestawie danych nie jest bezpieczną operacją: natychmiast wpływa na wszystkie zależne wykresy bez żadnej informacji zwrotnej.
  • Filtr Time Column Filter nie jest mechanizmem przypięcia do kolumny, a globalnym przełącznikiem czasu dla całego dashboarda.
  • Wersje 5.x i 6.x nie usuwają podstawowego problemu: logika wyboru czasu nadal znajduje się w models.py, bez refaktoringu architektury filtracji.
  • Jedynym pewnym sposobem izolacji jest fizyczne podzielenie zestawów danych lub przejście na parametryzowane wizualizacje SQL.

W Apache Superset filtracja po dacie pozostaje jednym z najbardziej słabych miejsc architektury. Brak wsparcia dla wielu osi czasowych na poziomie zestawu danych, surowe przypięcie do porządku alfabetycznego nazw oraz brak mechanizmu anotowania kolumn czynią niemożliwym prawidłowe modelowanie potoków zdarzeń z kilkoma wymiarami czasowymi. To szczególnie krytyczne dla analizy IoT, transakcji finansowych i logów mikroservisów, gdzie każda rekord zawiera co najmniej trzy metki czasowe: event_time, ingestion_time i processing_time. Społeczność proponuje poprawkę w ramach zgłoszenia #32496, jednak do tej pory nie ma pull requesta z implementacją. Póki co najlepszą praktyką jest projektowanie zestawów danych tak, aby każdy miał dokładnie jedną sensowną kolumnę czasową, lub rezygnacja z wbudowanych filtrów na rzecz kontrolowanych rozwiązań SQL.

— Editorial Team

Advertisement 728x90

Czytaj dalej