Generated Columns (생성 컬럼)

이 기능을 사용하려면 drizzle-orm@0.32.0 이상 및 drizzle-kit@0.23.0 이상이 필요합니다

  1. Virtual (또는 비영구) Generated Columns: 이 컬럼은 쿼리될 때마다 동적으로 계산됩니다. 데이터베이스에 저장 공간을 차지하지 않습니다.

  2. Stored (또는 영구) Generated Columns: 이 컬럼은 행이 삽입되거나 업데이트될 때 계산되며 그 값이 데이터베이스에 저장됩니다. 이를 통해 인덱싱이 가능하며, 각 쿼리마다 값을 다시 계산할 필요가 없어 쿼리 성능을 향상시킬 수 있습니다.

Generated columns의 구현 및 사용법은 SQL 데이터베이스마다 크게 다를 수 있습니다. PostgreSQL, MySQL, SQLite는 각각 generated columns에 대해 고유한 기능, 가능성 및 제한사항을 가지고 있습니다. 이 섹션에서는 각 데이터베이스 시스템에서 generated columns을 최대한 활용하는 방법을 이해하는 데 도움이 되도록 이러한 차이점을 상세히 살펴보겠습니다.

PostgreSQL
MySQL
SQLite
SingleStore (작업 중)
MSSQL
CockroachDB

데이터베이스 측

타입: STORED 전용

작동 방식

  • 삽입 또는 업데이트 시 다른 컬럼을 기반으로 값을 자동으로 계산합니다.

기능

  • 복잡한 표현식을 미리 계산하여 데이터 접근을 단순화합니다.
  • Generated columns에 대한 인덱스 지원으로 쿼리 성능을 향상시킵니다.

제한사항

  • 기본값을 지정할 수 없습니다.
  • 표현식은 다른 generated columns을 참조하거나 서브쿼리를 포함할 수 없습니다.
  • Generated column 표현식을 수정하려면 스키마 변경이 필요합니다.
  • 기본 키, 외래 키 또는 유니크 제약조건에서 직접 사용할 수 없습니다

자세한 정보는 PostgreSQL 문서를 확인하세요

Drizzle 측

Drizzle에서는 모든 컬럼 타입에 .generatedAlwaysAs() 함수를 지정하고 지원되는 SQL 쿼리를 추가하여 이 컬럼 데이터를 자동으로 생성할 수 있습니다.

기능

이 함수는 2가지 방법으로 generated 표현식을 받을 수 있습니다:

IMPORTANT

1.0.0-beta.12 버전부터 변경된 사항

이전 버전에서는 .generatedAlwaysAs()가 리터럴을 표현식으로 받을 수 있었습니다.

string

export const test = pgTable("test", {
    generatedName: text("gen_name").generatedAlwaysAs(`'hello world!'`),
});
CREATE TABLE "test" (
    "gen_name" text GENERATED ALWAYS AS ('hello world!') STORED
);

sql 태그 - Drizzle이 일부 값을 이스케이프하도록 하려는 경우

export const test = pgTable("test", {
    generatedName: text("gen_name").generatedAlwaysAs(sql`'hello "world"!'`),
});
CREATE TABLE "test" (
    "gen_name" text GENERATED ALWAYS AS ('hello "world"!') STORED
);

callback - 테이블의 컬럼을 참조해야 하는 경우

export const test = pgTable("test", {
    name: text("first_name"),
    generatedName: text("gen_name").generatedAlwaysAs(
      (): SQL => sql`'hi, ' || ${test.name} || '!'`
    ),
});
CREATE TABLE "test" (
    "first_name" text,
    "gen_name" text GENERATED ALWAYS AS ('hi, ' || "test"."first_name" || '!') STORED
);

예제 전체 텍스트 검색을 사용하는 generated columns

schema.ts
import { SQL, sql } from "drizzle-orm";
import { customType, index, integer, pgTable, text } from "drizzle-orm/pg-core";

const tsVector = customType<{ data: string }>({
  dataType() {
    return "tsvector";
  },
});

export const test = pgTable(
  "test",
  {
    id: integer("id").primaryKey().generatedAlwaysAsIdentity(),
    content: text("content"),
    contentSearch: tsVector("content_search", {
      dimensions: 3,
    }).generatedAlwaysAs(
      (): SQL => sql`to_tsvector('english', ${test.content})`
    ),
  },
  (t) => [
    index("idx_content_search").using("gin", t.contentSearch)
  ]
);
CREATE TABLE "test" (
	"id" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "test_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
	"content" text,
	"content_search" "tsvector" GENERATED ALWAYS AS (to_tsvector('english', "test"."content")) STORED
);
--> statement-breakpoint
CREATE INDEX "idx_content_search" ON "test" USING gin ("content_search");