[SW 개발자를 위한 성능 좋은 SQL 쿼리 작성법] 정리 1

Kim yohan·2025년 5월 5일
0

TIL

목록 보기
22/22

📌 인덱스 사용 여부 판단 (실행계획 확인)

  • 사용 O - type : const, range, ref
  • 사용 X - type : all

스캔 속도 비교

system > const > eq_ref > ref > range > index > all

  • const: PK로 동등조건(=) 조회
  • ref: PK 아닌 컬럼으로 동등조건(=) 조회
  • range: 범위 스캔

eq_ref

조건설명
조인 사용A JOIN B 와 같은 형태
조인 조건이 =ON A.col = B.col
비교 대상 컬럼이 유니크보통 B.col이 PK나 UNIQUE + NOT NULL
매칭되는 행이 정확히 1개각 A row마다 B에서 1개


📌 ANSI ISO 표준

: 관계형 데이터베이스에서 사용하는 공통 SQL 문법.
성능 & 유지보수성을 위해 사용하기!

ex)
(X) from a,b,c where ...
(X) 외부조인 시 * 사용 등



📌 where절 작성 순서

  • 작성 순서는 성능과 연관되는가?
    -> X. 상관없음. 옵티마이저가 관리
    대신, 유지보수 측면에서만 신경쓰기

  • FROM절의 JOIN 순서는 성능과 연관되는가?
    -> X. 상관없음. 옵티마이저가 관리
    대신, 유지보수 측면에서만 신경쓰기
    -> 단, INNER JOIN일 때만!! OUTER JOIN 사용시, 순서 영향 있음!!!

  • 스키마 이름 지정
    -> schema.object (NorthWind.orders)
    스키마 생략 시, ID 사용해 찾는 과정 발생.
    -> 미미하지만, 쌓이고 쌓이면 유의미한 차이 발생 가능!
    -> 되도록 붙이자!



📌 날짜시간 상수

  • datetime 자료형 (8byte)
    : 날짜(4byte) + 시간(4byte), 미리초까지 표기

  • datetime2 (6, 7, 8 byte)
    : 마이크로초까지 표기


MySQL datetime 상수 형식

권장

'YYYY-MM-DD HH:MM:SS'

허용

형식예시설명
'YYYY-MM-DD''2025-05-05'시간 생략 시 00:00:00 으로 처리됨
'YYYYMMDDHHMMSS''20250505133000'공백/구분자 없는 숫자 형태
'YY-MM-DD''25-05-05'연도 2자리. 해석에 주의 필요
'YYYY-MM-DDTHH:MM:SS''2025-05-05T13:30:00'ISO 8601 형식 일부 지원
NOW(), CURRENT_TIMESTAMP(함수)현재 날짜/시간 반환
UNIX_TIMESTAMP 형식FROM_UNIXTIME(1700000000)정수형 타임스탬프 변환

비허용

형식이유
'05/05/2025'미국식 슬래시 표기는 기본적으로 허용되지 않음
'May 5, 2025'영어로 된 날짜 형식은 MySQL에서 인식 안 됨
'2025-13-01', '2025-02-30'존재하지 않는 날짜는 오류 발생

DB2 timestamp 상수 형식

DB2에선 DATETIME 존재 X
그래서, TIMESTAMP를 대신 사용!

권장

'YYYY-MM-DD HH:MM:SS'

허용

형식예시설명
'YYYY-MM-DD''2025-05-05'DATE 타입에 사용, TIMESTAMP로 자동 변환 시 00:00:00 추가
'YYYY-MM-DD-HH.MM.SS''2025-05-05-13.30.00'Db2 고유 포맷 (클래식 스타일)
'YYYYMMDDHHMMSS''20250505133000'숫자 포맷으로도 가능 (명시적 변환 필요)

비허용

형식이유
'05/05/2025'슬래시 표기 불가
'May 5, 2025'자연어 표기 불가
'2025-05-05T13:30:00'ISO 8601 T 형식 기본 지원 안 됨 (CAST 필요)

✅ datetime, timestamp에 시간만 넣을 시
SQL SERVER에선 '1900-01-01'을 자동으로 보완해서 저장
MySQL, DB2에선 오류남.



📌 char vs varchar

오른쪽에 공백이 있는 상황 'hi '
char 자료형에 저장 시, 'hi' == 'hi '
varchar 자료형에 저장 시, 'hi' != 'hi '

원인

  • char은 고정형이기 때문에, 문자열 비교시 공백을 채움.
    CHAR(8)에 'AA'가 저장되면, 공백 6자리를 붙여 8자리로 만듬.

  • 그래서 varchar은 가변형이기 때문에, 다르다고 나오는 것임.
    MySQL 5.0.3 이전에는 varchar 저장 시 공백이 제거되었지만,
    이후에는 공백 유지됨.

  • 따라서,
    VARCHAR 자료형 값에서 조회 시 TRIM사용 대신, 저장 시 TRIM 사용하자.
    이름, 주소 등 길이가 변할 수 있는 값은 VARCHAR 사용하고,
    사번, 주민등록번호 등 길이가 일정한 값은 CHAR 사용하자.



📌 의미 오류(Semantic Error) 유형

  1. PK에 IS NULL, DISTINCT 쓰는 경우
  2. LIKE 조건이 EQUAL 조건과 다름 없는 경우
  3. IF EXISTS 조건 속 SELECT에 불필요한 요소
  4. ORDER BY에 불필요하게 많은 컬럼 사용.
    (ex. ORDER BY PK1, PK2, COL1 이면 COL1은 의미 없음.)
  5. GROUP BY HAVING 사용 시, WHERE절에 적는 것이 나은 경우.
  6. 중복 요소 없는데, UNION 쓰는 경우.
    (UNION은 중복 제거 기능이 있기 때문에, 이런 경우 UNION ALL 쓰는게 적합.
    UNION 써도 옵티마이저가 UNION ALL을 써주긴 하지만, 쿼리 작성 단계에서 잘 작성하는게 나음.)
  7. NOT IN 서브쿼리에 NULL값 나오는 경우.
  8. WHERE 조건에 따라 불필요한 JOIN


📌 SARG(Search Argument, 검색 인수)

  • Predicate에서 검색 대상 및 범위를 제한할 수 있는 식
  • 전체 테이블을 조회하지 않도록 제한해주는 식
  • 그래야 해당 열에 인덱스 사용 및 쿼리 최적화 가능
  • 검색을 제한하지 않는 Non-SARG인지 검토해봐야함!

✅ Predicate
WHERE 조건, HAVING 조건, JOIN 조건 등 TRUE, FALSE, UNKNOWN으로 결정나는 조건식



❓ 궁금점

  1. 특정 테이블 JOIN하기 전에 row 수를 줄여놓는게 의미가 있을까?
    JOIN 시, where절에서 조건 거는 것과 차이가 있나?

✅ 의미 있는 경우

상황JOIN 전에 row 줄이기 효과
테이블이 수백만 건이고, 대부분 오래된 데이터✅ 불필요한 조인 줄이기 가능
조인할 테이블이 여러 개일 때✅ 조인 순서 최적화에 도움
복잡한 JOIN + WHERE 조합에 옵티마이저가 헷갈릴 때✅ 명시적으로 순서 유도 가능
특정 조인에 LEFT JOIN, OUTER JOIN 같이 의미가 바뀌는 조건이 있을 때✅ 의미 제어 가능

💡 해결
대부분의 현대 DBMS 옵티마이저는 최적화를 잘 해주기 때문에,
실행계획을 살펴보고 결정하자!

  1. 클러스터형 인덱스 vs 비클러스터형 인덱스?
profile
꾸준히 성실하게

0개의 댓글