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

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

이 글에서 다루는 내용

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

2202H invalid tablesample argument 는?

PostgreSQL 에러 코드 2202H (invalid tablesample argument)TABLESAMPLE 절을 사용할 때 샘플링 메서드에 전달된 인자 값이 유효하지 않을 경우 발생하는 에러입니다. PostgreSQL의 TABLESAMPLE 기능은 테이블에서 무작위로 일정 비율의 행을 추출할 수 있는 기능으로, BERNOULLISYSTEM 두 가지 기본 메서드를 제공합니다. 이 에러는 샘플링 비율로 0 미만이거나 100 초과의 값을 입력하거나, 허용되지 않는 형식의 인자를 전달했을 때 주로 발생하며, 데이터 분석이나 통계 샘플링 쿼리를 작성하는 실무 환경에서 예상치 못하게 마주칠 수 있는 에러입니다.


주요 발생 원인

1. 샘플링 비율이 허용 범위(0~100)를 벗어난 경우

TABLESAMPLE 메서드의 인자는 퍼센트(%) 단위로 0 이상 100 이하의 값이어야 합니다. 가장 흔한 실수는 소수점 비율을 0~1 사이의 값(예: 0.1)으로 입력하거나, 100을 초과하는 값(예: 150)을 입력하는 경우입니다. PostgreSQL은 이 범위를 벗어난 값에 대해 즉시 2202H 에러를 발생시킵니다.

2. 음수 또는 NULL 값을 샘플링 인자로 전달한 경우

샘플링 비율에 음수 값이나 NULL을 전달하는 경우에도 이 에러가 발생합니다. 동적 쿼리를 구성하거나 애플리케이션에서 변수를 통해 샘플링 비율을 전달할 때, 값 유효성 검사를 생략하면 이러한 상황이 발생할 수 있습니다. 특히 사용자 입력값을 그대로 쿼리에 반영하는 경우 더욱 주의가 필요합니다.

3. 커스텀 TABLESAMPLE 메서드에 잘못된 인자 형식을 전달한 경우

PostgreSQL은 확장 기능을 통해 커스텀 TABLESAMPLE 메서드를 정의할 수 있으며(tsm_system_rows 등), 각 메서드마다 허용하는 인자의 형식과 범위가 다를 수 있습니다. 예를 들어 tsm_system_rows는 행 개수(정수)를 인자로 받는데, 음수나 0을 전달하면 에러가 발생합니다. 커스텀 메서드의 문서를 확인하지 않고 기본 메서드와 동일한 방식으로 인자를 전달하면 이 에러가 발생할 수 있습니다.


해결 방법

원인 1 해결: 샘플링 비율을 0 이상 100 이하로 수정

잘못된 예시 — 범위를 벗어난 값 사용:

-- 에러 발생: 인자가 100을 초과함
SELECT *
FROM orders TABLESAMPLE BERNOULLI(150);

-- 에러 발생: 소수점 비율을 0~1 사이로 잘못 입력
SELECT *
FROM orders TABLESAMPLE SYSTEM(0.01);  -- 1%가 아니라 0.01%로 인식될 수 있음

올바른 예시 — 유효한 범위 사용:

-- 올바른 사용: 전체 데이터의 10% 샘플 추출 (BERNOULLI 방식)
SELECT *
FROM orders TABLESAMPLE BERNOULLI(10);

-- 올바른 사용: 전체 데이터의 5% 샘플 추출 (SYSTEM 방식, 블록 단위 샘플링)
SELECT *
FROM orders TABLESAMPLE SYSTEM(5);

-- 0.5% 미만의 소량 샘플이 필요한 경우
SELECT *
FROM orders TABLESAMPLE BERNOULLI(0.5);

원인 2 해결: 동적 쿼리에서 인자 유효성 검사 추가

-- 잘못된 예시: 변수 유효성 검사 없이 사용
DO $$
DECLARE
    sample_rate NUMERIC := -10;  -- 잘못된 값
BEGIN
    -- 이 쿼리는 2202H 에러 발생
    EXECUTE format('SELECT * FROM orders TABLESAMPLE BERNOULLI(%s)', sample_rate);
END;
$$;

-- 올바른 예시: 실행 전 유효성 검사 적용
DO $$
DECLARE
    sample_rate NUMERIC := -10;  -- 외부에서 전달받은 값
BEGIN
    -- 유효성 검사: 0 초과 100 이하인지 확인
    IF sample_rate <= 0 OR sample_rate > 100 THEN
        RAISE EXCEPTION '샘플링 비율은 0 초과 100 이하여야 합니다. 현재 값: %', sample_rate;
    END IF;

    EXECUTE format('SELECT * FROM orders TABLESAMPLE BERNOULLI(%s)', sample_rate);
END;
$$;

-- 실무용: LEAST/GREATEST로 범위를 강제로 클램핑하는 방법
DO $$
DECLARE
    raw_input NUMERIC := 150;  -- 외부 입력값
    safe_rate NUMERIC;
BEGIN
    -- 0.1 ~ 100 사이로 클램핑
    safe_rate := GREATEST(0.1, LEAST(100, raw_input));
    
    EXECUTE format('SELECT COUNT(*) FROM orders TABLESAMPLE BERNOULLI(%s)', safe_rate);
END;
$$;

원인 3 해결: 커스텀 TABLESAMPLE 메서드의 올바른 인자 사용

-- tsm_system_rows 확장 설치 (슈퍼유저 권한 필요)
CREATE EXTENSION IF NOT EXISTS tsm_system_rows;

-- 잘못된 예시: tsm_system_rows에 음수 또는 0 전달
SELECT *
FROM orders TABLESAMPLE system_rows(-100);  -- 에러 발생

SELECT *
FROM orders TABLESAMPLE system_rows(0);  -- 에러 발생

-- 올바른 예시: 양의 정수 행 수 전달
SELECT *
FROM orders TABLESAMPLE system_rows(1000);  -- 최대 1000행 샘플링

-- BERNOULLI vs SYSTEM vs system_rows 비교 예시
-- BERNOULLI: 행 단위 확률 기반 (정확하지만 느림)
SELECT COUNT(*) FROM large_table TABLESAMPLE BERNOULLI(1);

-- SYSTEM: 블록 단위 샘플링 (빠르지만 편향 가능)
SELECT COUNT(*) FROM large_table TABLESAMPLE SYSTEM(1);

-- system_rows: 정확한 행 수 지정 가능
SELECT COUNT(*) FROM large_table TABLESAMPLE system_rows(10000);

예방 방법

1. 샘플링 비율을 전달하는 함수/프로시저에 CHECK 로직 내장화

애플리케이션이나 ETL 파이프라인에서 TABLESAMPLE을 동적으로 사용하는 경우, 반드시 래퍼(wrapper) 함수를 만들어 인자 유효성 검사를 중앙화하세요. 이렇게 하면 여러 쿼리에서 반복적으로 검사 로직을 작성하지 않아도 되고, 향후 메서드가 변경되더라도 한 곳만 수정하면 됩니다.

-- 안전한 샘플링 래퍼 함수 예시
CREATE OR REPLACE FUNCTION safe_sample_query(
    p_table_name TEXT,
    p_sample_rate NUMERIC,
    p_method TEXT DEFAULT 'BERNOULLI'
)
RETURNS TEXT
LANGUAGE plpgsql
AS $$
BEGIN
    -- 메서드 유효성 검사
    IF p_method NOT IN ('BERNOULLI', 'SYSTEM') THEN
        RAISE EXCEPTION '지원하지 않는 샘플링 메서드입니다: %', p_method;
    END IF;

    -- 비율 유효성 검사
    IF p_sample_rate <= 0 OR p_sample_rate > 100 THEN
        RAISE EXCEPTION '샘플링 비율은 0 초과 100 이하여야 합니다: %', p_sample_rate;
    END IF;

    RETURN format(
        'SELECT * FROM %I TABLESAMPLE %s(%s)',
        p_table_name,
        p_method,
        p_sample_rate
    );
END;
$$;

-- 사용 예시
SELECT safe_sample_query('orders', 10, 'BERNOULLI');

2. 코드 리뷰 및 테스트 환경에서 경계값 테스트 의무화

TABLESAMPLE을 사용하는 쿼리는 반드시 0, 100, 음수, NULL, 101 등의 경계값과 비정상값으로 테스트하는 절차를 팀 내 코드 리뷰 체크리스트에 포함하세요. CI/CD 파이프라인에 해당 테스트 케이스를 추가하면 배포 전에 문제를 사전에 차단할 수 있습니다.


관련 에러

  • 22003 (numeric_value_out_of_range): 숫자 값 자체가 데이터 타입의 범위를 벗어날 때 발생하며, 2202H와 혼동될 수 있습니다.
  • 22023 (invalid_parameter_value): 함수나 연산에 유효하지 않은 파라미터가 전달될 때 발생하는 일반적인 에러로, 커스텀 TABLESAMPLE 메서드에서 발생할 수 있습니다.
  • 42601 (syntax_error): TABLESAMPLE 절의 문법 자체가 잘못된 경우 발생하며, 인자 관련 에러인 2202H보다 먼저 발생합니다.
  • 2202G (invalid_tablesample_repeat): TABLESAMPLE의 REPEATABLE 절에 잘못된 시드(seed) 값을 전달했을 때 발생하는 에러로, 2202H와 유사한 상황에서 마주칩니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기