본문으로 바로가기 본문 바로가기
WIKI 기술 지식 베이스

생성된 컬럼 (Generated columns)

원문 보기 위키 갱신

D1의 생성된 컬럼(generated columns)을 소개하는 문서예요. 데이터를 테이블에 쓰거나 읽을 때 자동으로 정규화해서, 쿼리를 더 쉽게 만들고 복잡한 애플리케이션 로직의 필요를 줄여줘요.

출처: 문서

본문

Generated columns

이 기능은 데이터를 테이블에 쓰거나 읽을 때 데이터를 정규화할 수 있게 해줘서, 쿼리가 더 쉬워지고 복잡한 애플리케이션 로직이 덜 필요해져요.

생성된 컬럼에는 인덱스를 정의할 수도 있어요. 자주 쿼리하는 필드에 대해 쿼리 성능을 크게 높일 수 있거든요.

생성된 컬럼의 유형

생성된 컬럼에는 두 가지 유형이 있어요.

  • VIRTUAL (기본값): 컬럼이 읽을 때 생성돼요. 저장 공간을 소모하지 않는다는 장점이 있지만, 특히 큰 쿼리에서는 컴퓨팅 시간이 늘어나(따라서 쿼리 성능이 떨어질 수 있어요)요.

  • STORED: 컬럼이 행이 쓰일 때 생성돼요. 일반 컬럼처럼 저장 공간을 차지하지만, 읽을 때마다 컬럼을 생성할 필요가 없어서 읽기 쿼리 성능을 높일 수 있어요.

생성된 컬럼 표현식에서 생략하면 생성된 컬럼은 기본적으로 VIRTUAL 유형이 돼요. 생성된 컬럼이 컴퓨팅 집약적일 때는 STORED 유형을 권장해요. 예를 들어 큰 JSON 구조를 파싱할 때요.

생성된 컬럼 정의하기

생성된 컬럼은 CREATE TABLE 문으로 테이블을 만들 때 정의하거나, 이후에 ALTER TABLE 문으로 정의할 수 있어요.

생성된 컬럼을 정의하는 테이블을 만들려면 AS 키워드를 사용해요.

CREATE TABLE some_table (
    -- other columns omitted
    some_generated_column AS <function_that_generates_the_column_data>
)

구체적인 예로, 다음 JSON 센서 데이터에서 location 값을 자동으로 추출하려면 JSON 데이터의 원본 표현을 저장하는 raw_data 컬럼을 기반으로 location(유형 TEXT)라는 생성된 컬럼을 정의할 수 있어요.

{
    "measurement": {
        "temp_f": "77.4",
        "aqi": [21, 42, 58],
        "o3": [18, 500],
        "wind_mph": "13",
        "location": "US-NY"
    }
}

$.measurement.location 값을 가진 생성된 컬럼을 정의하려면 json_extract 함수를 사용해 그 행에 쓸 때마다 raw_data 컬럼에서 값을 추출할 수 있어요.

CREATE TABLE sensor_readings (
    event_id INTEGER PRIMARY KEY,
    timestamp INTEGER NOT NULL,
    raw_data TEXT,
    location as (json_extract(raw_data, '$.measurement.location')) STORED
);

생성된 컬럼은 선택적으로 column_name GENERATED ALWAYS AS <function> [STORED|VIRTUAL] 구문으로 지정할 수 있어요. GENERATED ALWAYS 구문은 선택사항이며 생략해도 생성된 컬럼의 동작은 바뀌지 않아요.

기존 테이블에 생성된 컬럼 추가하기

생성된 컬럼은 기존 테이블에도 추가할 수 있어요. sensor_readings 테이블에 생성된 location 컬럼이 없다면 ALTER TABLE 문으로 추가할 수 있어요.

ALTER TABLE sensor_readings
ADD COLUMN location as (json_extract(raw_data, '$.measurement.location'));

이것은 각 읽기 쿼리에서 json_extract를 실행하는 VIRTUAL 생성된 컬럼을 정의해요.

생성된 컬럼 정의는 직접 수정할 수 없어요. 생성된 컬럼이 데이터를 생성하는 방식을 바꾸려면 ALTER TABLE table_name REMOVE COLUMN 후 ADD COLUMN으로 생성된 컬럼을 다시 정의하거나, 새 정의로 ADD COLUMN을 호출하기 전에 ALTER TABLE table_name RENAME COLUMN current_name TO new_name으로 기존 컬럼 이름을 바꾸면 돼요.

예시

생성된 컬럼은 json_extract 같은 JSON 함수에만 국한되지 않아요. 생성된 컬럼이 어떻게 생성될지 정의하는 데 거의 모든 사용 가능한 함수를 쓸 수 있어요.

예를 들어 앞선 sensor_reading 테이블의 timestamp 컬럼을 기반으로 date 컬럼을 생성해서, 데이터베이스 안에서 Unix 타임스탬프를 YYYY-MM-dd 형식으로 자동 변환할 수 있어요.

ALTER TABLE your_table
-- date(timestamp, 'unixepoch') converts a Unix timestamp to a YYYY-MM-dd formatted date
ADD COLUMN formatted_date AS (date(timestamp, 'unixepoch'))

또는 미래 날짜를 계산하는 expires_at 컬럼을 정의하고, 쿼리에서 그 날짜를 기준으로 필터링할 수도 있어요.

-- Filter out "expired" results based on your generated column:
-- SELECT * FROM your_table WHERE current_date() > expires_at
ALTER TABLE your_table
-- calculates a date (YYYY-MM-dd) 30 days from the timestamp.
ADD COLUMN expires_at AS (date(timestamp, '+30 days'));

추가 고려 사항

  • 테이블에는 생성되지 않은 컬럼이 최소 1개 이상 있어야 해요. 생성된 컬럼만으로 테이블을 정의할 수는 없어요.

  • 표현식은 같은 테이블과 행의 다른 컬럼만 참조할 수 있으며, 결정적 함수 (deterministic functions) ↗︎만 사용해야 해요. random() 같은 함수, 서브쿼리, 집계 함수는 생성된 컬럼을 정의하는 데 사용할 수 없어요.

  • ALTER TABLE ... ADD COLUMN으로 기존 테이블에 추가하는 컬럼은 VIRTUAL이어야 해요. 기존 테이블에는 STORED 컬럼을 추가할 수 없어요.

더 알아보기 (Learn more)