Historycznie zadania agregacji i grupowania w SQL często pojawiały się przy generowaniu raportów i analizie. Już w relacyjnych bazach danych z lat 80-tych pojawiały się podstawowe funkcje agregujące (SUM, COUNT, AVG), ale przy dużych zbiorach danych klasyczne GROUP BY spowolniało. Pojawiał się problem skalowalności: zapytania z dziesiątkami milionów rekordów i wieloma grupami blokowały tabele i spowalniały pracę.
Problem polega na tym, że przy nieefektywnym podejściu serwer SQL marnuje wiele zasobów na sortowanie, tabele pośrednie i odczyt z dysku. Szczególnie trudno jest, gdy grupowanie odbywa się po kilku kolumnach lub przy dynamicznie dobieranych danych do agregacji.
Rozwiązanie polega na odpowiednim budowaniu indeksów na kolumnach grupujących, wykorzystaniu partycjonowania, "półagregacji" i optymalizacji struktury zapytania. Dla zadań analityki biznesowej często stosuje się strukturalne Common Table Expressions (CTE), materializowane widoki oraz funkcje okienkowe.
Przykład kodu:
WITH PreAgg AS ( SELECT customer_id, region, SUM(amount) AS total_amount FROM sales WHERE sale_date >= '2024-01-01' GROUP BY customer_id, region ) SELECT region, COUNT(DISTINCT customer_id) AS customers, SUM(total_amount) AS region_amount FROM PreAgg GROUP BY region ORDER BY region_amount DESC;
Kluczowe cechy:
Czy wydajność GROUP BY zależy od kolejności kolumn w SELECT?
Nie, kolejność kolumn w SELECT nie wpływa na szybkość, krytyczne jest tylko to, po jakich kolumnach następuje grupowanie i czy są na nich indeksy.
Czy każda kolumna w SELECT przy GROUP BY musi mieć funkcję agregującą?
Nie jest to konieczne, jeśli kolumna jest zawarta w GROUP BY, można ją wyświetlać bez agregacji. Jeśli kolumna nie uczestniczy w grupowaniu — musi być agredowana.
SELECT department, MIN(salary) FROM employees GROUP BY department;
Czy można zagnieździć jeden GROUP BY w drugim dla wielopoziomowej agregacji?
Tak, zagnieżdżone CTE lub podzapytania pozwalają na wykonywanie "wielopiętrowych" agregacji z wynikami pośrednimi.
WITH Step1 AS ( SELECT customer, SUM(amount) AS cust_sum FROM orders GROUP BY customer ) SELECT COUNT(*) FROM Step1 WHERE cust_sum > 10000;
Analityk tworzy raport z wieloma GROUP BY na tabeli z 200 mln rekordów bez indeksów i bez podziału próbki, cały biuro o 9 rano "zawiesza się". Wykonanie trwa 40 minut.
Plusy:
Minusy:
Inżynier wykorzystuje CTE do wstępnej filtracji, właściwe indeksy na potrzebnych polach i dzieli agregację na kilka etapów. Raport buduje się w 5 sekund.
Plusy:
Minusy: