[PostgreSQL] HypoPG를 통한 인덱스 가설 검증

[원본 링크]

데이터 사이즈가 커지다보면, 인덱스를 추가할때마다 걸리는 시간과 부하가 선형적으로 증가하게 된다.

그래서 인덱스를 추가하고 삭제하면서 성능을 실험하는데 제약이 많이 걸리게 되는데, 이거도 운영상황에서는 큰 벽이다.
hyperpg는 이런 딜레이를 줄이기 위한 확장이다.




동작 원리와 한계

PG는 항상 테이블의 통계와 cost를 기준으로 인덱스를 선택하고 쿼리를 실행한다.
그래서 꼭 인덱스를 만들지 않더라도 cost 계산만 할 수 있으면 인덱스 선택을 시뮬레이션하는 것이 가능하다.

여기서 hyperpg는 "가상 인덱스"라는 개념을 도입해서 이러한 cost 계산을 대행해주는 역할을 한다, "인덱스를 이렇게 만들면 이 인덱스가 걸릴까?" 정도를 검증해주는 것이다.

때문에 진짜 실제 실행계획과 동일하지는 않을 수 있다. 이러한 데이터 분포와 조건에서 이 인덱스가 선택될지 아닐지 정도만 확인이 가능하다. 실제 상황에서 인덱스가 100% 걸린다는 보장도 없고, 얼마나 걸리는지는 알 수 없다.




설치

서드파티 확장이지만 RDS 등 주요 Managed DB에서는 기본으로 설치가 되어있다.
그냥 바로 깔면 된다.

CREATE EXTENSION hypopg;




사용해보기

먼저 테스트용 테이블을 하나 만들어보자.
다음은 50만개짜리 적당한 데이터셋 생성 쿼리다.

CREATE TABLE public.hypopg_orders AS
SELECT
    g::bigint AS id,

    -- 고객 10만 명, 고객당 약 50건
    ((g - 1) % 100000 + 1)::int AS customer_id,

    CASE
        WHEN ((g::bigint * 37) % 1000) < 10 THEN 'pending'
        WHEN ((g::bigint * 37) % 1000) < 50 THEN 'cancelled'
        ELSE 'paid'
    END::text AS status,

    timestamptz '2024-01-01 00:00:00+00'
        + (
            ((g::bigint * 48271) % 63072000)
            * interval '1 second'
        ) AS created_at,

    ((g::bigint * 7919) % 500000)::int AS amount_cents,

    md5(g::text) || md5((g::bigint * 17)::text) AS payload
FROM generate_series(1, 5000000) AS g;

그리고 다음과 같이 적당히 느린 쿼리를 날려보면

EXPLAIN
SELECT
    id,
    customer_id,
    status,
    created_at,
    amount_cents
FROM public.hypopg_orders
WHERE customer_id = 4242
ORDER BY created_at DESC
LIMIT 20;

당연히 비효율적으로 돌 것이다.
테이블을 풀스캔한 다음에 id로 필터링하고, created_at으로 정렬을 수행한다.

하지만 다음과 같이 가상 인덱스를 만들면

SELECT *
FROM hypopg_create_index(
    'CREATE INDEX ON public.hypopg_orders (customer_id)'
);

explain에서의 결과가 바뀐다.

가상 인덱스를 선택해서 스캔하는 것으로 바뀌었다.
물론 이건 시뮬레이션에 불과하므로, 그냥 쿼리를 날리거나 analyze 모드로 explain할 때는 무시된다.


실행하면 씹힌다.
그래서 실험이 끝났다면 실제로 인덱스를 만들어줘야 한다.

그리고 가상 인덱스를 전부 날리려면 전용 리셋 함수를 쓰면 된다.

그렇다.
쓰는게 어렵진 않다.



참조
https://www.postgresql.org/about/news/introducing-hypopg-hypothetical-indexes-for-postgresql-1593/
https://github.com/HypoPG/hypopg
https://hypopg.readthedocs.io/en/rel1_stable/

Search