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:
- 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 Filterglobalnie przekreśladefault_time_columndla 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.
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ść;
- Przykład:
SELECT
ts AS time_dimension,
user_id,
event_type,
payload
FROM messages
WHERE ts IS NOT NULL
- Używanie
extra_jsondo 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_atiupdated_attraktowane są jako równorzędne strings do sortowania. - Zmiana
default_time_columnw zestawie danych nie jest bezpieczną operacją: natychmiast wpływa na wszystkie zależne wykresy bez żadnej informacji zwrotnej. - Filtr
Time Column Filternie 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
Brak komentarzy.