그룹 집계

그룹 집계 (Group Aggregation)

대부분의 데이터 시스템처럼 Apache Flink도 내장 및 사용자 정의 집계 함수를 지원해요. 사용자 정의 함수는 사용 전에 카탈로그에 등록되어야 해요. 집계 함수는 여러 입력 행에서 단일 결과를 계산해요. 예를 들어 행 집합에 대해 COUNT, SUM, AVG(평균), MAX(최대), MIN(최소)을 계산하는 집계가 있어요.

출처: 문서

본문

SELECT COUNT(*) FROM Orders

스트리밍 질의의 경우 Flink가 종료되지 않는 연속 질의를 실행한다는 점을 이해하는 것이 중요해요. 대신 입력 테이블의 갱신에 따라 결과 테이블을 갱신해요. 위 질의에 대해 Flink는 Orders 테이블에 새 행이 삽입될 때마다 갱신된 count를 출력해요.

Apache Flink는 데이터 집계를 위한 표준 GROUP BY 절을 지원해요.

SELECT COUNT(*)
FROM Orders
GROUP BY order_id

스트리밍 질의의 경우 질의 결과를 계산하는 데 필요한 상태가 무한정 커질 수 있어요. 상태 크기는 그룹 수와 집계 함수의 수·유형에 따라 달라져요. 예를 들어 MIN/MAX는 상태 크기가 크고 COUNT는 저렴해요. 과도한 상태 크기를 막기 위해 적절한 상태 TTL(time-to-live)을 가진 질의 구성을 제공할 수 있어요. 이는 질의 결과의 정확성에 영향을 줄 수 있다는 점에 주의해요. 자세한 내용은 query configuration을 참고해요.

Apache Flink는 Group Aggregation을 위한 여러 성능 튜닝 방법을 제공해요. Performance Tuning을 참고해요.

DISTINCT 집계 (DISTINCT Aggregation)

Distinct 집계는 집계 함수를 적용하기 전에 중복 값을 제거해요. 다음 예제는 Orders 테이블의 총 행 수 대신 고유 order_id의 수를 세어요.

SELECT COUNT(DISTINCT order_id) FROM Orders

스트리밍 질의의 경우 질의 결과를 계산하는 데 필요한 상태가 무한정 커질 수 있어요. 상태 크기는 대부분 고유 행 수와 그룹이 유지되는 시간에 따라 달라지며, 수명이 짧은 group by 윈도우는 문제가 되지 않아요. 과도한 상태 크기를 막기 위해 적절한 상태 TTL을 가진 질의 구성을 제공할 수 있어요. 이는 질의 결과의 정확성에 영향을 줄 수 있다는 점에 주의해요. 자세한 내용은 query configuration을 참고해요.

GROUPING SETS

Grouping sets는 표준 GROUP BY로 설명할 수 있는 것보다 더 복잡한 그룹핑 연산을 허용해요. 행은 각 지정된 grouping set에 따라 별도로 그룹핑되고, 각 그룹에 대해 단순 GROUP BY 절과 마찬가지로 집계가 계산돼요.

SELECT supplier_id, rating, COUNT(*) AS total
FROM (VALUES
('supplier1', 'product1', 4),
('supplier1', 'product2', 3),
('supplier2', 'product3', 3),
('supplier2', 'product4', 4))
AS Products(supplier_id, product_id, rating)
GROUP BY GROUPING SETS ((supplier_id, rating), (supplier_id), ())

결과:

+-------------+--------+-------+
| supplier_id | rating | total |
+-------------+--------+-------+
| supplier1 | 4 | 1 |
| supplier1 | (NULL) | 2 |
| (NULL) | (NULL) | 4 |
| supplier1 | 3 | 1 |
| supplier2 | 3 | 1 |
| supplier2 | (NULL) | 2 |
| supplier2 | 4 | 1 |
+-------------+--------+-------+

GROUPING SETS의 각 하위 목록은 0개 이상의 컬럼이나 표현식을 지정할 수 있으며 GROUP BY 절에 직접 사용된 것과 같은 방식으로 해석돼요. 빈 grouping set은 모든 행이 단일 그룹으로 집계됨을 의미하며, 입력 행이 없어도 출력돼요. grouping 컬럼이나 표현식에 대한 참조는 해당 컬럼이 나타나지 않는 grouping set의 결과 행에서 null 값으로 대체돼요.

스트리밍 질의의 경우 질의 결과를 계산하는 데 필요한 상태가 무한정 커질 수 있어요. 상태 크기는 group set 수와 집계 함수 유형에 따라 달라져요. 과도한 상태 크기를 막기 위해 적절한 상태 TTL을 가진 질의 구성을 제공할 수 있어요. 이는 질의 결과의 정확성에 영향을 줄 수 있다는 점에 주의해요.

ROLLUP

ROLLUP은 공통 유형의 grouping set을 지정하는 축약 표기법이에요. 주어진 표현식 목록과 그 목록의 모든 접두사(빈 목록 포함)를 나타내요. 예를 들어 다음 질의는 위와 동등해요.

SELECT supplier_id, rating, COUNT(*)
FROM (VALUES
('supplier1', 'product1', 4),
('supplier1', 'product2', 3),
('supplier2', 'product3', 3),
('supplier2', 'product4', 4))
AS Products(supplier_id, product_id, rating)
GROUP BY ROLLUP (supplier_id, rating)

CUBE

CUBE는 공통 유형의 grouping set을 지정하는 축약 표기법이에요. 주어진 목록과 그 모든 가능한 부분집합(멱집합)을 나타내요. 예를 들어 다음 두 질의는 동등해요.

SELECT supplier_id, rating, product_id, COUNT(*)
FROM (VALUES
('supplier1', 'product1', 4),
('supplier1', 'product2', 3),
('supplier2', 'product3', 3),
('supplier2', 'product4', 4))
AS Products(supplier_id, product_id, rating)
GROUP BY CUBE (supplier_id, rating, product_id)

SELECT supplier_id, rating, product_id, COUNT(*)
FROM (VALUES
('supplier1', 'product1', 4),
('supplier1', 'product2', 3),
('supplier2', 'product3', 3),
('supplier2', 'product4', 4))
AS Products(supplier_id, product_id, rating)
GROUP BY GROUPING SETS (
( supplier_id, product_id, rating ),
( supplier_id, product_id ),
( supplier_id, rating ),
( supplier_id ),
( product_id, rating ),
( product_id ),
( rating ),
( )
)

HAVING

HAVING은 조건을 만족하지 않는 그룹 행을 제거해요. HAVING은 WHERE와 다르다: WHERE는 GROUP BY 전에 개별 행을 필터링하고, HAVING은 GROUP BY가 만든 그룹 행을 필터링해요. 조건에서 참조되는 각 컬럼은 집계 함수 안에 나타나지 않으면 모호함 없이 grouping 컬럼을 참조해야 해요.

SELECT SUM(amount)
FROM Orders
GROUP BY users
HAVING SUM(amount) > 50

HAVING이 있으면 GROUP BY 절이 없더라도 질의는 그룹핑된 질의가 돼요. 이는 질의가 GROUP BY 절 없이 집계 함수를 포함할 때와 같아요. 질의는 선택된 모든 행을 단일 그룹으로 간주하고, SELECT 목록과 HAVING 절은 집계 함수 안에서만 테이블 컬럼을 참조할 수 있어요. 그러한 질의는 HAVING 조건이 참이면 단일 행을, 참이 아니면 0개 행을 출력해요.

더 알아보기 (Learn more)