minSimpleState — 모든 입력 값의 최솟값을 단순 상태로 구하기

minSimpleState — 모든 입력 값의 최솟값을 단순 상태로 구하기

minSimpleStatemin 함수에 SimpleState 결합자를 적용해서 모든 입력 값 중 최솟값을 SimpleAggregateFunction 타입으로 반환하는 방법을 보여드릴게요.

출처: 문서

본문

min 함수에 SimpleState 결합자를 적용하면 모든 입력 값 중 최솟값을 반환해요. 결과는 SimpleAggregateFunction 타입으로 반환해요.

일일 온도 측정값을 추적하는 테이블을 사용하는 실용적인 예제를 살펴볼게요. 각 위치에 대해 기록된 최저 온도를 유지하고 싶다고 해요. min과 함께 SimpleAggregateFunction 타입을 사용하면 더 낮은 온도가 들어올 때 저장된 값을 자동으로 갱신해요. 원시 온도 측정값을 위한 원본 테이블을 만들어요:

CREATE TABLE raw_temperature_readings
(
    location_id UInt32,
    location_name String,
    temperature Int32,
    recorded_at DateTime DEFAULT now()
)
    ENGINE = MergeTree()
ORDER BY (location_id, recorded_at);

최저 온도를 저장할 집계 테이블을 만들어요:

CREATE TABLE temperature_extremes
(
    location_id UInt32,
    location_name String,
    min_temp SimpleAggregateFunction(min, Int32),  -- Stores minimum temperature
    max_temp SimpleAggregateFunction(max, Int32)   -- Stores maximum temperature
)
ENGINE = AggregatingMergeTree()
ORDER BY location_id;

삽입된 데이터에 대한 삽입 트리거 역할을 하면서 위치별 최저·최고 온도를 유지하는 Incremental materialized view를 만들어요:

CREATE MATERIALIZED VIEW temperature_extremes_mv
TO temperature_extremes
AS SELECT
    location_id,
    location_name,
    minSimpleState(temperature) AS min_temp,     -- Using SimpleState combinator
    maxSimpleState(temperature) AS max_temp      -- Using SimpleState combinator
FROM raw_temperature_readings
GROUP BY location_id, location_name;

초기 온도 측정값을 삽입해요:

INSERT INTO raw_temperature_readings (location_id, location_name, temperature) VALUES
(1, 'North', 5),
(2, 'South', 15),
(3, 'West', 10),
(4, 'East', 8);

이 측정값들은 materialized view가 자동으로 처리해요. 현재 상태를 확인해볼게요:

SELECT
    location_id,
    location_name,
    min_temp,     -- Directly accessing the SimpleAggregateFunction values
    max_temp      -- No need for finalization function with SimpleAggregateFunction
FROM temperature_extremes
ORDER BY location_id;
┌─location_id─┬─location_name─┬─min_temp─┬─max_temp─┐
│           1 │ North         │        5 │        5 │
│           2 │ South         │       15 │       15 │
│           3 │ West          │       10 │       10 │
│           4 │ East          │        8 │        8 │
└─────────────┴───────────────┴──────────┴──────────┘

데이터를 더 삽입해요:

INSERT INTO raw_temperature_readings (location_id, location_name, temperature) VALUES
    (1, 'North', 3),
    (2, 'South', 18),
    (3, 'West', 10),
    (1, 'North', 8),
    (4, 'East', 2);

새 데이터 이후 갱신된 최저·최고 값을 확인해요:

SELECT
    location_id,
    location_name,
    min_temp,  
    max_temp
FROM temperature_extremes
ORDER BY location_id;
┌─location_id─┬─location_name─┬─min_temp─┬─max_temp─┐
│           1 │ North         │        3 │        8 │
│           1 │ North         │        5 │        5 │
│           2 │ South         │       18 │       18 │
│           2 │ South         │       15 │       15 │
│           3 │ West          │       10 │       10 │
│           3 │ West          │       10 │       10 │
│           4 │ East          │        2 │        2 │
│           4 │ East          │        8 │        8 │
└─────────────┴───────────────┴──────────┴──────────┘

위에서 각 위치마다 두 개의 삽입된 값이 보이는데요, 아직 part들이 병합(그리고 AggregatingMergeTree에 의한 집계)되지 않았기 때문이에요. 부분 상태에서 최종 결과를 얻으려면 GROUP BY를 추가해야 해요:

SELECT
    location_id,
    location_name,
    min(min_temp) AS min_temp,  -- Aggregate across all parts 
    max(max_temp) AS max_temp   -- Aggregate across all parts
FROM temperature_extremes
GROUP BY location_id, location_name
ORDER BY location_id;

이제 기대한 결과를 얻을 수 있어요:

┌─location_id─┬─location_name─┬─min_temp─┬─max_temp─┐
│           1 │ North         │        3 │        8 │
│           2 │ South         │       15 │       18 │
│           3 │ West          │       10 │       10 │
│           4 │ East          │        2 │        8 │
└─────────────┴───────────────┴──────────┴──────────┘

SimpleState를 사용하면 부분 집계 상태를 합치기 위해 Merge 결합자를 쓸 필요가 없어요.

더 알아보기 (Learn more)