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

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

이 글에서 다루는 내용

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

2202H invalid tablesample argument 는?

PostgreSQL 에러 코드 2202H는 TABLESAMPLE 절에 잘못된 인수가 전달되었을 때 발생하는 에러입니다. TABLESAMPLE은 테이블에서 통계적으로 샘플링된 행을 반환하는 기능으로, BERNOULLI 또는 SYSTEM 메서드와 함께 0에서 100 사이의 퍼센트 값을 인수로 받습니다. 유효하지 않은 범위의 값이나 잘못된 데이터 타입이 인수로 사용될 경우 이 에러가 발생하며, 특히 대용량 데이터 분석 및 샘플링 작업 시 자주 마주칠 수 있습니다.

주요 발생 원인

  • 범위를 벗어난 샘플링 퍼센트 값 사용

TABLESAMPLE의 인수는 반드시 0 초과, 100 이하의 숫자여야 합니다. 0 이하이거나 100을 초과하는 값, 혹은 정확히 0인 값을 전달하면 PostgreSQL은 해당 값이 유효한 샘플링 비율이 아니라고 판단하여 2202H 에러를 반환합니다. 실무에서 동적으로 계산된 퍼센트 값을 쿼리에 주입할 때 유효 범위 검증을 생략하면 이 문제가 빈번하게 발생합니다.

  • NULL 또는 잘못된 데이터 타입 전달

TABLESAMPLE 절의 인수로 NULL 값이나 숫자가 아닌 데이터 타입을 전달하면 에러가 발생합니다. 예를 들어, 애플리케이션 코드에서 변수를 바인딩할 때 초기화되지 않은 변수나 문자열 타입의 변수를 그대로 넘기는 경우가 해당됩니다. 이는 특히 PL/pgSQL 함수나 동적 SQL 생성 로직 내에서 파라미터 처리가 미흡할 때 자주 나타납니다.

  • 지원하지 않는 TABLESAMPLE 메서드와의 인수 불일치

PostgreSQL 기본 제공 메서드인 BERNOULLI와 SYSTEM 외에도 확장 모듈(예: tsm_system_rows, tsm_system_time)을 통해 커스텀 샘플링 메서드를 사용할 수 있습니다. 이때 각 메서드가 요구하는 인수의 타입, 개수, 범위가 다를 수 있는데, 이를 혼동하여 잘못된 인수를 전달하면 2202H 에러가 발생합니다. 예를 들어 tsm_system_rows는 퍼센트가 아닌 행 수를 인수로 요구하며, 음수나 0을 전달하면 에러가 발생합니다.

해결 방법

원인 1: 범위를 벗어난 퍼센트 값 수정

올바른 퍼센트 범위(0 초과 ~ 100 이하)를 사용하도록 쿼리를 수정합니다.

-- 잘못된 예: 0 또는 음수, 100 초과 값 사용
SELECT * FROM orders TABLESAMPLE BERNOULLI(0);    -- 에러 발생
SELECT * FROM orders TABLESAMPLE BERNOULLI(-5);   -- 에러 발생
SELECT * FROM orders TABLESAMPLE BERNOULLI(150);  -- 에러 발생

-- 올바른 예: 0 초과 100 이하의 값 사용
SELECT * FROM orders TABLESAMPLE BERNOULLI(10);   -- 10% 샘플링
SELECT * FROM orders TABLESAMPLE SYSTEM(25);      -- 25% 샘플링 (블록 단위)

-- 동적 퍼센트 값 사용 시 범위 클램핑 처리
DO $$
DECLARE
    v_sample_pct NUMERIC := -5; -- 잘못된 값이 들어온 상황
    v_safe_pct   NUMERIC;
BEGIN
    -- GREATEST/LEAST 를 이용해 유효 범위로 클램핑
    v_safe_pct := GREATEST(0.001, LEAST(100, v_sample_pct));
    RAISE NOTICE '안전한 샘플링 비율: %', v_safe_pct;
    -- 이후 동적 SQL에 v_safe_pct 사용
END;
$$;

원인 2: NULL 및 타입 불일치 해결

TABLESAMPLE 인수가 반드시 유효한 숫자인지 사전 검증 후 사용합니다.

-- 잘못된 예: NULL 전달
SELECT * FROM orders TABLESAMPLE BERNOULLI(NULL); -- 에러 발생

-- PL/pgSQL 함수 내에서 NULL 안전 처리 예제
CREATE OR REPLACE FUNCTION sample_orders(p_pct NUMERIC DEFAULT 10)
RETURNS SETOF orders AS $$
DECLARE
    v_pct NUMERIC;
BEGIN
    -- NULL 체크 및 범위 검증
    IF p_pct IS NULL THEN
        RAISE EXCEPTION 'sample percentage must not be NULL';
    END IF;

    IF p_pct <= 0 OR p_pct > 100 THEN
        RAISE EXCEPTION 'sample percentage must be between 0 (exclusive) and 100 (inclusive), got: %', p_pct;
    END IF;

    v_pct := p_pct;

    RETURN QUERY EXECUTE
        format('SELECT * FROM orders TABLESAMPLE BERNOULLI(%s)', v_pct);
END;
$$ LANGUAGE plpgsql;

-- 안전한 호출
SELECT * FROM sample_orders(15);

-- 잘못된 호출 시 명확한 에러 메시지 반환
SELECT * FROM sample_orders(NULL);
SELECT * FROM sample_orders(-10);

원인 3: 확장 메서드별 올바른 인수 사용

각 TABLESAMPLE 메서드의 인수 규격을 확인하고 맞게 사용합니다.

-- tsm_system_rows 확장 설치 (행 개수 기반 샘플링)
CREATE EXTENSION IF NOT EXISTS tsm_system_rows;

-- 잘못된 예: BERNOULLI 방식의 퍼센트를 tsm_system_rows에 적용
-- tsm_system_rows는 행 수를 인수로 받으므로 의미가 다름
SELECT * FROM orders TABLESAMPLE SYSTEM_ROWS(0);   -- 에러: 0 이하 불가
SELECT * FROM orders TABLESAMPLE SYSTEM_ROWS(-100); -- 에러: 음수 불가

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

-- tsm_system_time 확장 (시간 기반 샘플링, 밀리초 단위)
CREATE EXTENSION IF NOT EXISTS tsm_system_time;

-- 올바른 예: 밀리초 단위 시간 전달 (양수여야 함)
SELECT * FROM orders TABLESAMPLE SYSTEM_TIME(100); -- 100ms 동안 스캔

-- 어떤 TABLESAMPLE 메서드가 설치되어 있는지 확인
SELECT a.amname, p.proname
FROM pg_am a
JOIN pg_proc p ON p.oid = a.amhandler
WHERE a.amtype = 's'; -- 's' = sample method

예방 방법

  • 입력 값 유효성 검사 레이어 도입

애플리케이션 코드 또는 데이터베이스 함수 레이어에서 TABLESAMPLE 인수로 사용할 값을 반드시 사전 검증하는 습관을 들여야 합니다. 특히 사용자 입력이나 외부 시스템으로부터 전달받는 동적 파라미터의 경우, 데이터베이스에 전달하기 전에 허용 범위를 명시적으로 체크하거나 클램핑 처리를 적용하십시오. 아래와 같이 공통 유틸리티 함수를 만들어 재사용하는 것을 권장합니다.

“`sql

— 안전한 샘플링 비율 반환 유틸리티 함수

CREATE OR REPLACE FUNCTION safe_sample_pct(

p_pct NUMERIC,

p_min NUMERIC DEFAULT 0.001,

p_max NUMERIC DEFAULT 100

) RETURNS NUMERIC AS $$

BEGIN

IF p_pct IS NULL THEN

RETURN p_min; — NULL이면 최솟값 반환

END IF;

RETURN GREATEST(p_min, LEAST(p_max, p_pct));

END;

$$ LANGUAGE plpgsql IMMUTABLE;

— 사용 예

SELECT * FROM orders TABLESAMPLE BERNOULLI(safe_sample_pct(10));

SELECT * FROM orders TABLESAMPLE BERNOULLI(safe_sample_pct(NULL)); — 0.001% 반환

“`

  • TABLESAMPLE 사용 전 메서드별 문서 및 확장 사양 숙지

BERNOULLI, SYSTEM, SYSTEM_ROWS, SYSTEM_TIME 등 각각의 메서드가 요구하는 인수의 타입과 범위가 다르므로, 새로운 샘플링 메서드를 도입할 때는 반드시 공식 문서와 확장 모듈의 사양을 확인해야 합니다. 또한 CI/CD 파이프라인에 TABLESAMPLE 관련 쿼리를 포함한 단위 테스트를 추가하여, 잘못된 인수로 인한 에러가 프로덕션 환경에 도달하지 않도록 사전 차단하는 체계를 갖추는 것이 중요합니다.

관련 에러

  • 22003 (numeric_value_out_of_range): 숫자 값이 허용 범위를 초과했을 때 발생하며, 2202H와 함께 나타날 수 있습니다.
  • 22P02 (invalid_text_representation): 문자열을 숫자로 캐스팅하는 과정에서 실패할 때 발생하며, 동적 SQL에서 잘못된 타입을 TABLESAMPLE 인수로 전달하는 경우와 연관됩니다.
  • 42883 (undefined_function): 설치되지 않은 TABLESAMPLE 확장 메서드(예: SYSTEM_ROWS)를 사용하려 할 때 발생하며, 2202H 에러 이전에 먼저 마주치게 되는 에러입니다.
  • 2202G (invalid_tablesample_repeat): TABLESAMPLE 절의 REPEATABLE 시드 값이 유효하지 않을 때 발생하는 에러로, 2202H와 함께 TABLESAMPLE 관련 에러 그룹에 속합니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기