728x90
실무를 경험하다가 운 좋게 DBA 분에게 배운 정보들 몇 가지를 작성해 봄
1. BETWEEN AND보단 부등호 사용을 권장
- 적은 데이터를 조회할 때 BETWEEN AND와 부등호의 차이는 미미할 수 있지만, 대규모 사이트에서 억단위의 데이터에서는 차이가 발생한다고 함
2. WHERE 조건보다 JOIN에 걸 수 있는 조건은 JOIN의 ON에 작성하는 것을 권장
- 데이터 조인으로 조회 시 100만건이 조회되는데, 조건식에 의해 50만건만 조회된다고 하였을 때 100만건을 모두 조회한 후 WHERE 문에서 50만 건이 걸러지는 것보다, JOIN을 하면서 거르게 되면 100만건 → 50만건이 아니라 최초부터 50만건만 조회가 된다고 함
-- 아래의 쿼리에서 100만 건의 데이터 조회
SELECT
*
FROM
A
JOIN B ON A.JOIN_ID = B.JOIN_ID
;
-- 아래의 쿼리에서 50만건의 데이터가 조회
-- 단, 최초 조인 시 100만건의 데이터에서 WHERE 문으로 50만건이 걸러짐
SELECT
*
FROM
A
JOIN B ON A.JOIN_ID = B.JOIN_ID
WHERE 1=1
AND B.STATUS_CODE = 1
;
-- 아래의 쿼리에서 50만건의 데이터가 조회
-- 조인을 하면서 B.STATUS_CODE가 1이 아닌 것은 걸러지면서 조인 됨
SELECT
*
FROM
A
JOIN B ON A.JOIN_ID = B.JOIN_ID
AND B.STATUS_CODE = 1
;
3. 좌변은 최대한 손대지 않고 우변을 손대는 것을 권장
- INDEX가 걸려있는 컬럼에 SUBSTRING, LEFT와 같은 함수를 사용하여 조작을 할 경우 INDEX SCAN이 아닌 FULL SCAN이 되어 가능한 좌변은 고정으로 하고 우변을 조작을 하는 것이 속도적으로 월등히 뛰어남
- 단, 아래의 경우에는 좌변을 조작해도 됨
-- 인덱스 사용 안됨
WHERE LEFT(USER_ID, 3) = 'abc'
-- 인덱스 사용 가능
WHERE USER_ID LIKE 'abc%'
- 컬럼을 조작할 수 밖에 없는 상황
Ex) 날짜 데이터(CREATE_DATE)가 '20250702135122' 같은 식으로 들어가 있을 때, 연도별로 통계를 내야한다거나 25년도의 데이터만 추출을 하려고 할 때 LEFT(CREATE_DATE, 4)를 사용할 수 밖에 없음 - 인덱싱이 걸려있지 않은 컬럼의 경우
4. COUNT() 사용 시 *(아스타) 보다는 1을 사용하는 것을 권장
- 데이터베이스의 저장 방식(Storage Architecture)에는 행 기반(Row-based) 스토리지 엔진과 열 기반(Column-based) 스토리지 엔진이 존재
- 행 기반(Row-based) : MySQL(InnoDB), PostgreSQL, Oracle, CUBRID
- 행 기반 스토리지 엔진 : COUNT(*)와 COUNT(1)은 동일하게 처리 됨
- 열 기반(Column-based) : Amazon Redshift, ClickHouse, Apache Parquet, SAP HANA, Vertica
- 열 기반 스토리지 엔진 : COUNT(*)보다는 COUNT(1) 또는 COUNT(컬럼)이 더 성능적으로 안정적일 수 있음
- 행 기반(Row-based) : MySQL(InnoDB), PostgreSQL, Oracle, CUBRID
- 열 기반 DBMS를 사용 중 매우 큰 테이블에 COUNT(*)를 수행하면, 모든 열을 스캔해야 한다고 판단될 경우 다음과 같은 현상이 발생할 수 있다고 함
- 메모리 사용량 급증
- 디스크 I/O가 과도하게 발생
- CPU 연산이 많아져 쿼리가 느려지거나 DB가 뻗는 현상
ChatGPT의 의견
1. BETWEEN AND보다는 부등호 사용 권장
정리 상태: 거의 정확함
- BETWEEN은 양 끝값을 포함하는 조건 (>= AND <=)으로 처리 됨
- 옵티마이저는 내부적으로 BETWEEN을 >= AND <=로 바꿔서 처리하기 때문에 기본적으로 성능 차이는 없음
- 다만 날짜나 범위 조건에서 쿼리 범위를 정확하게 설정하지 않으면 예상보다 많은 데이터가 걸릴 수 있음
💡 보완 팁 : 성능 차이보다는 명확한 범위 지정과 인덱스 활용의 적절성 때문에 부등호를 권장하는 경우가 많습니다
2. WHERE보다 JOIN ON에 조건을 거는 것이 좋다
정리 상태: 핵심 개념은 맞음, 약간의 보완 필요
- 대부분의 RDBMS 옵티마이저는 JOIN ON과 WHERE에 조건이 있으면 자동으로 조건을 푸시 다운(Predicate Pushdown)해서 효율적으로 처리합니다
- 하지만 옵티마이저가 충분히 똑똑하지 않거나, 매우 복잡한 쿼리일 경우에는 JOIN ON에 조건을 명시해주는 것이 계획 수립에 도움될 수 있습니다
💡 보완 팁:
- "JOIN의 ON에 조건을 주면 조인 전 필터링된다" → 일반적인 옵티마이저는 WHERE 조건도 필터링을 미리 적용합니다
- 하지만 명시적으로 ON 절에 조건을 줄 경우, 조인 대상이 되는 데이터의 양이 줄어드는 것을 개발자가 의도적으로 알려주는 것이므로 쿼리 가독성 및 옵티마이저 힌트 역할을 할 수 있습니다
최근 챗지피티의 성능이 많이 올라왔기 때문에 아예 무시할 수는 없겠지만 여전히 맹신할 수는 없는 정보이기는 하다.
무엇보다도 DBA분은 경험을 기반으로 말씀을 해주셨을 것이기 때문에 DBA분께 배운 것을 기반으로 쿼리를 작성하는 것의 습관을 들이는 것이 좋을 것으로 보이고, BETWEEN AND와 부등호의 성능 차이 같은 부분은 물론 경험을 하면서 습득을 하는 것이겠지만, 뉴비인 사람들이 어떻게 판단할 수 있는 지 여쭤보았는데 큰 사이트에서 수천, 수억의 데이터에서 시도를 해보는 수밖에 없다는 답변을 받았다.
결국 개인의 프로젝트에서 이러한 성능을 체크하기에는 어려움이 있을 것으로 보이고, 점차 성장하여 더욱 큰 규모의 프로젝트에서 실무를 경험하게 될 때 이러한 것들을 테스트하면서 직접 깨닫게 되어야할 것 같다.
728x90