CodeGym /행동 /SQL SELF /대용량 데이터용 분석 함수 최적화: 인덱싱과 파티셔닝

대용량 데이터용 분석 함수 최적화: 인덱싱과 파티셔닝

SQL SELF
레벨 60 , 레슨 3
사용 가능

데이터가 많아지면(회사 채팅방에서 데드라인 얘기 나오는 것처럼) SELECT나 데이터 처리 쿼리가 느려지기 시작해. 주요 원인은 이거야:

  1. 인덱스 없음. PostgreSQL이 쿼리 실행할 때 테이블 전체를 스캔해야 하면(이걸 "Seq Scan" — 시퀀셜 스캔이라고 해), 쿼리가 훨씬 오래 걸릴 수 있어.
  2. 비효율적인 SQL 쿼리. 쿼리를 최적화 생각 안 하고 짜면, 인덱스가 있어도 실무에서 고생할 수 있어. 예를 들어 WHERE에서 중요한 조건 빼먹었어? 그럼 쿼리 오래 걸릴 준비해야지.
  3. 한 테이블에 데이터가 너무 많음. 예를 들어, 모든 연도 판매 데이터를 한 번에 분석하려고 하면, 인덱스만으로도 부족할 수 있어.

근데 걱정하지 마! 이럴 때 쓸 수 있는 두 가지 검증된 방법이 있어: 인덱싱이랑 파티셔닝.

쿼리 속도 올리기 위한 인덱스 사용

인덱스 만드는 간단한 예시 보여줄게:

CREATE INDEX idx_sales_date ON sales(transaction_date);
  • 여기서 idx_sales_date는 인덱스 이름이야(원하는 대로 지어도 되지만, 의미 있게 짓는 게 좋아).
  • ON sales(transaction_date) — 어떤 테이블, 어떤 컬럼에 인덱스 만드는지 지정하는 거야.

이 인덱스는 transaction_date 컬럼으로 자주 필터링할 때 특히 유용해.

이 인덱스 덕분에 빨라지는 쿼리 예시:

SELECT *
FROM sales
WHERE transaction_date BETWEEN '2023-01-01' AND '2023-12-31';

복합 키 인덱싱

쿼리에서 여러 컬럼(region이랑 product_id 같은 거) 조합을 자주 쓰면, 복합 인덱스 만드는 것도 고려해봐:

CREATE INDEX idx_sales_region_product ON sales(region, product_id);

이제 이런 쿼리들이 훨씬 빨라져:

SELECT *
FROM sales
WHERE region = 'North America' AND product_id = 42;

유니크 인덱스 사용하기

유니크 인덱스는 검색만 빠르게 해주는 게 아니라, 컬럼 값의 유일성도 보장해줘. 예를 들어:

CREATE UNIQUE INDEX idx_unique_customer_email ON customers(email);

이제 같은 이메일 가진 고객을 실수로 두 번 등록할 수 없어.

분석 함수용 인덱싱

SUM, COUNT, AVG 같은 데이터 분석 함수도 인덱스를 활용해서 더 빨리 계산할 수 있어. 예시:

CREATE INDEX idx_sales_amount ON sales(amount);

쿼리:

SELECT SUM(amount)
FROM sales 
WHERE transaction_date >= '2023-01-01';

이 인덱스 덕분에 쿼리가 더 빨라질 거야.

대용량 데이터 처리를 위한 테이블 파티셔닝

테이블 파티셔닝은 큰 테이블을 더 작은 논리적 조각(파티션)으로 나누는 거야. 예를 들어 sales 테이블을 연도별로 나눌 수 있어: sales_2021, sales_2022 등등.

이거 어렵다고 생각해? 사실 PostgreSQL이 생각보다 쉽게 해줘.

파티셔닝 종류

  1. 범위 파티셔닝 (Range Partitioning). 예를 들어 날짜처럼, 값의 범위로 데이터 나누기.
  2. 리스트 파티셔닝 (List Partitioning). 예를 들어 지역처럼, 정확한 값으로 데이터 나누기.
  3. 해시 파티셔닝 (Hash Partitioning). 해시 함수로 데이터 나누기(직접 쓸 일은 드물어).

파티셔닝 테이블 만들기

연도별로 파티셔닝된 판매 테이블 만들어보자.

CREATE TABLE sales (
    id SERIAL PRIMARY KEY,
    transaction_date DATE NOT NULL,
    amount NUMERIC,
    region TEXT
) PARTITION BY RANGE (transaction_date);

이제 연도별 파티션을 만들어보자:

CREATE TABLE sales_2021 PARTITION OF sales
FOR VALUES FROM ('2021-01-01') TO ('2022-01-01');

CREATE TABLE sales_2022 PARTITION OF sales
FOR VALUES FROM ('2022-01-01') TO ('2023-01-01');

날짜로 필터링하는 쿼리는 자동으로 해당 파티션만 사용해. EXPLAIN 명령어로 쉽게 확인할 수 있어.

파티셔닝 예시

2021년 판매만 합산하는 쿼리는 이렇게 생겼을 거야:

SELECT SUM(amount)
FROM sales
WHERE transaction_date BETWEEN '2021-01-01' AND '2021-12-31';

보다시피, PostgreSQL은 전체 테이블이 아니라 sales_2021 파티션만 읽어.

예시: 지역별 메트릭 계산 최적화

예를 들어, 지역별로 총 판매액을 계산하고 싶다고 해보자. 인덱스랑 파티션 없으면 진짜 오래 걸려. 먼저 region 컬럼에 인덱스 만들어보자:

CREATE INDEX idx_sales_region ON sales(region);

쿼리:

SELECT region, SUM(amount)
FROM sales
GROUP BY region;

이제 인덱스 덕분에 처리 속도가 빨라져.

예시: 시간 데이터 파티셔닝

트랜잭션이나 로그처럼 시간 데이터는 월별로 파티션을 나누는 게 좋아. 예를 들어:

CREATE TABLE sales_monthly PARTITION BY RANGE (transaction_date);

CREATE TABLE sales_jan_2023 PARTITION OF sales_monthly
FOR VALUES FROM ('2023-01-01') TO ('2023-02-01');

쿼리:

SELECT SUM(amount)
FROM sales_monthly
WHERE transaction_date >= '2023-01-01' AND transaction_date < '2023-02-01';

이렇게 하면 PostgreSQL이 sales_jan_2023 파티션만 읽어서 더 빨라져.

예시: 인덱싱과 파티셔닝 같이 쓰기

인덱싱이랑 파티셔닝을 같이 쓰면 성능을 극대화할 수 있어. 예를 들어, 각 파티션 안에 인덱스를 만들 수도 있어. 예시:

CREATE INDEX idx_sales_amount_jan_2023 ON sales_jan_2023(amount);

흔한 실수 피하는 법

성능 문제의 많은 원인은 인덱스나 파티셔닝을 잘못 써서 생겨. 예를 들어:

  • 인덱스가 너무 많으면 INSERT 작업이 느려질 수 있어.
  • 파티션은 균등하게 데이터가 들어가게 설계해야 해. 너무 작거나 너무 큰 파티션은 성능을 떨어뜨려.
  • 최적화하기 전에 성능 분석(EXPLAIN ANALYZE)을 안 해보는 건, 자동차 고치면서 보닛도 안 열어보는 거랑 똑같아.

항상 네 최적화가 실제로 속도 향상에 도움이 되는지 체크하고, 실험하는 걸 두려워하지 마!

코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION