PostgreSQL 2202G 오류 원인과 해결 방법 완벽 가이드

2202G
2026년 06월 10일 | DBMS Error 가이드

이 글에서 다루는 내용

2202G 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.

2202G invalid tablesample repeat 는?

PostgreSQL 에러 코드 2202G: invalid tablesample repeatTABLESAMPLE 절에서 사용하는 반복(repeat) 시드(seed) 값이 유효하지 않을 때 발생하는 에러입니다. TABLESAMPLE은 테이블에서 무작위 샘플 데이터를 추출할 때 사용하는 기능으로, REPEATABLE 옵션을 통해 동일한 시드 값을 지정하면 매번 동일한 샘플 결과를 재현할 수 있습니다. 이 에러는 REPEATABLE 절에 전달되는 인자 값이 허용 범위를 벗어났거나, 올바르지 않은 데이터 타입이 지정되었을 때 발생합니다.


주요 발생 원인

1. REPEATABLE 절에 허용 범위를 벗어난 숫자 값 입력

TABLESAMPLEREPEATABLE 절은 내부적으로 난수 생성기(random seed)를 초기화하는 데 사용됩니다. PostgreSQL에서 허용하는 시드 값의 범위는 샘플링 메서드(BERNOULLI, SYSTEM 등)와 버전에 따라 다를 수 있으며, 일반적으로 유효하지 않은 부동소수점 값(NaN, Infinity 등)이나 극단적인 범위의 값을 전달하면 이 에러가 발생합니다. 예를 들어, REPEATABLE(NULL) 또는 REPEATABLE('NaN'::float8)처럼 잘못된 값을 넘기는 경우가 대표적입니다.

2. 동적 쿼리 또는 애플리케이션 코드에서 잘못된 시드 값 생성

애플리케이션 레이어에서 시드 값을 동적으로 생성하여 SQL 쿼리에 바인딩할 때, 타입 변환 오류나 예외 상황(예: None, NaN, 빈 문자열 등)으로 인해 유효하지 않은 값이 전달될 수 있습니다. 특히 Python, Java 등 외부 언어에서 파라미터를 바인딩할 때 None이나 float('nan')이 그대로 SQL로 전달되는 경우가 많습니다. 이 경우 에러 메시지가 애플리케이션 단에서 잘 드러나지 않아 디버깅이 어렵습니다.

3. 커스텀 TABLESAMPLE 메서드 또는 확장 모듈과의 충돌

PostgreSQL은 CREATE OPERATOR CLASS나 확장 모듈(extension)을 통해 커스텀 샘플링 메서드를 등록할 수 있습니다. 이때 커스텀 메서드가 시드 값에 대한 유효성 검증 로직을 잘못 구현하거나, 기대하는 범위와 실제 전달된 값이 다를 경우에도 2202G 에러가 발생할 수 있습니다. 서드파티 확장 모듈을 사용하는 환경에서는 해당 모듈의 문서를 반드시 확인해야 합니다.


해결 방법

원인 1 해결: 유효한 시드 값 사용

REPEATABLE 절에는 반드시 유한한(finite) 부동소수점 숫자를 사용해야 합니다. 아래와 같이 올바른 값을 지정하세요.

-- 잘못된 예: NaN 또는 NULL 사용 (에러 발생)
SELECT * FROM orders TABLESAMPLE BERNOULLI(10) REPEATABLE('NaN'::float8);
-- ERROR:  invalid tablesample repeat

SELECT * FROM orders TABLESAMPLE BERNOULLI(10) REPEATABLE(NULL);
-- ERROR:  invalid tablesample repeat

-- 올바른 예: 정수 또는 유한한 부동소수점 값 사용
SELECT * FROM orders TABLESAMPLE BERNOULLI(10) REPEATABLE(42);

-- 재현 가능한 샘플 추출 (동일한 시드로 동일한 결과 보장)
SELECT * FROM orders TABLESAMPLE SYSTEM(5) REPEATABLE(12345);

-- 현재 타임스탬프 기반 시드 (재현 불필요 시)
SELECT * FROM orders TABLESAMPLE BERNOULLI(10) REPEATABLE(
    EXTRACT(EPOCH FROM NOW())::bigint
);

원인 2 해결: 애플리케이션에서 시드 값 검증

애플리케이션에서 동적으로 시드 값을 생성할 경우, SQL에 바인딩하기 전에 반드시 유효성 검사를 수행하세요.

-- 시드 값이 유효한지 확인하는 헬퍼 함수 작성
CREATE OR REPLACE FUNCTION safe_tablesample(
    p_table_name TEXT,
    p_pct FLOAT,
    p_seed FLOAT
)
RETURNS SETOF RECORD
LANGUAGE plpgsql
AS $$
BEGIN
    -- 시드 값이 NULL이거나 무한대이거나 NaN인 경우 기본값으로 대체
    IF p_seed IS NULL OR p_seed != p_seed OR p_seed = 'Infinity'::float OR p_seed = '-Infinity'::float THEN
        p_seed := 1.0;  -- 기본 시드 값
        RAISE NOTICE 'Invalid seed value detected. Using default seed: %', p_seed;
    END IF;

    RETURN QUERY EXECUTE format(
        'SELECT * FROM %I TABLESAMPLE BERNOULLI(%s) REPEATABLE(%s)',
        p_table_name, p_pct, p_seed
    );
END;
$$;

-- 사용 예
SELECT * FROM safe_tablesample('orders', 10.0, NULL);
SELECT * FROM safe_tablesample('orders', 10.0, 99.5);

-- Python 등 외부 코드에서 안전하게 파라미터 바인딩하는 패턴 (psycopg2 예시 주석)
-- seed = user_input if (user_input is not None and not math.isnan(user_input)) else 1.0
-- cursor.execute("SELECT * FROM orders TABLESAMPLE BERNOULLI(10) REPEATABLE(%s)", (seed,))

원인 3 해결: 커스텀 샘플링 메서드 시드 범위 확인

-- 현재 등록된 TABLESAMPLE 메서드 확인
SELECT amname, amtype
FROM pg_am
WHERE amtype = 's';  -- 's' = sample method

-- 커스텀 메서드의 핸들러 함수 확인
SELECT p.proname, p.prosrc
FROM pg_proc p
JOIN pg_am a ON a.amhandler = p.oid
WHERE a.amtype = 's';

-- BERNOULLI/SYSTEM 기본 메서드로 대체하여 테스트
SELECT * FROM orders TABLESAMPLE BERNOULLI(10) REPEATABLE(42);
SELECT * FROM orders TABLESAMPLE SYSTEM(10) REPEATABLE(42);

-- 커스텀 메서드 비활성화 후 기본 메서드 사용
-- (확장 기반이라면 DROP EXTENSION 또는 ALTER TABLE 로 샘플 메서드 변경)

예방 방법

1. 시드 값 입력 시 유효성 검증 로직을 항상 포함하라

REPEATABLE 절에 외부 입력을 그대로 사용하는 것은 매우 위험합니다. 데이터베이스 레이어와 애플리케이션 레이어 양쪽 모두에서 시드 값이 유한한 숫자인지 확인하는 로직을 구현하세요. 특히 CI/CD 파이프라인에 통합 테스트를 추가하여 경계값(NULL, NaN, Infinity, 빈 문자열 등)에 대한 테스트 케이스를 자동화하면 사전에 문제를 방지할 수 있습니다.

-- 시드 검증 예시: CHECK 제약 조건을 활용한 입력 테이블 설계
CREATE TABLE sampling_config (
    id SERIAL PRIMARY KEY,
    table_name TEXT NOT NULL,
    sample_pct FLOAT CHECK (sample_pct > 0 AND sample_pct <= 100),
    seed_value FLOAT CHECK (
        seed_value IS NOT NULL
        AND seed_value > '-Infinity'::float
        AND seed_value < 'Infinity'::float
        AND seed_value = seed_value  -- NaN 방지: NaN != NaN
    )
);

2. TABLESAMPLE 사용 시 래퍼 함수(Wrapper Function)를 표준화하라

프로젝트 전체에서 TABLESAMPLE을 직접 사용하는 대신, 검증 로직이 내장된 래퍼 함수나 뷰를 표준화하여 사용하는 것을 권장합니다. 이렇게 하면 시드 값 검증, 로깅, 샘플링 비율 제한 등의 정책을 중앙에서 관리할 수 있고, 에러 발생 시 일관된 에러 처리가 가능합니다. 팀 내 쿼리 작성 가이드라인에 해당 내용을 포함시켜 모든 개발자가 안전한 방식으로 샘플링 기능을 사용할 수 있도록 하세요.


관련 에러

  • 22003: numeric_value_out_of_rangeTABLESAMPLE 퍼센트 값(0~100)이 범위를 벗어났을 때 발생하며, 2202G와 함께 자주 마주치는 에러입니다.
  • 2202H: invalid tablesample argument — 시드 값이 아닌 샘플링 비율 인자(BERNOULLI(percent))가 유효하지 않을 때 발생하는 유사 에러로, 2202G와 함께 TABLESAMPLE 관련 에러 쌍으로 묶어서 처리하는 것이 좋습니다.
  • 42P01: undefined_tableTABLESAMPLE을 사용한 대상 테이블이 존재하지 않을 때 발생하며, 동적 쿼리에서 자주 함께 발생합니다.
  • 42601: syntax_errorTABLESAMPLE 문법 자체를 잘못 사용했을 때 발생하며, 2202G로 진행되기 전 단계에서 만날 수 있는 에러입니다.

DBMS 에러 코드 시리즈

주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.

본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.

댓글 남기기