[DB] SQL SELECT * 사용 시 주의점

Arthur·2024년 5월 22일
0
post-thumbnail

작성하게 된 계기


SELECT 쿼리 작성 시 *는 상당히 편한 기능 중 하나입니다.
해당 레코드의 모든 칼럼의 데이터를 조회할수 있습니다.

그래서 취준생 시절 학습 단계에서는 SELECT 쿼리 작성 시 상당히 많이 사용했었습니다.

하지만 취업 후 게임 서버 업무를 진행하면서 * 보다는 직접 칼럼을 명시하는게 안전 하다는 것을 알게되었습니다.



* 사용 시 문제점


1. 불필요한 데이터 전송

  • 모든컬럼을 선택하기 때문에 필요하지않은 데이터도 전송될 수 있다.
    • 네트워크 대역폭 낭비와 메모리를 불필요하게 사용하게 된다.

2. 인덱스 사용 저하

  • 모든 컬럼을 포함하기 때문에 인덱스 활용이 제한될 수 있다.

3. 스키마 변경의 위험

  • 테이블 구조가 변경되면 예기치 않은 결과를 반환할 수 있다.
    • 새로운 컬럼이 추가되거나 컬럼이 삭제될 경우 애플리케이션 코드가 제대로 작동하지 않을 수 있다.


더 큰 문제들이 있겠지만 이렇게 3가지 정도만 정리를 해봤습니다.
위 내용은 다른 블로그를 보거나 chatGPT에 물어보면 쉽게 나오는 내용입니다.

단순히 이론적인 부분이 아닌 *의 문제점을 직접 확인해볼 방법을 찾아봤습니다.

각 SQL문의 실행계획(EXPLAIN) 비교


1053개 정도의 더미 데이터가 들어이는 PostBox(우편함) 테이블을 기준으로 테스트 해봤습니다.
(아래 실행 된 쿼리의 실행계획은 각 환경, DB 설계에 따라 다를 수 있습니다. 참고만 부탁드립니다.)

쿼리문에 * 을 사용 했을 때

EXPLAIN SELECT * FROM PostBox;

실행 계획을 보면 typeALL이 적혀 있기 때문에 풀 스캔을 한다는 것을 알 수 있습니다.
당연히 전체 조회를 하는 쿼리이기 때문에 풀 스캔을 한다고 생각할 수 있습니다.

하지만 쿼리문에 인덱스 칼럼을 명시 하면 실행계획에 다른 결과가 나오게 됩니다.



쿼리문에 인덱스 칼럼만 명시 했을 때

EXPLAIN SELECT Id FROM PostBox;

인덱스 칼럼인 Id를 명시 한 결과 typeindex가 적혀있고, ExtraUsing index가 출력되게됩니다.

  • Extra에 Using index가 표시되면 커버링 인덱스가 적용된 것입니다.
    • 커버링 인덱스 : 쿼리의 모든 항목이 인덱스 컬럼으로 이루어진 상태

EXPLAIN SELECT Id, Username FROM PostBox;

하지만 쿼리에 인덱스가 아닌 칼럼 Username을 추가하면 type이 ALL로 출력되게됩니다.
반대로 인덱스 칼럼만 추가를 하면 인덱스를 타게 됩니다.



*을 사용하는 쿼리문에 WHERE절을 추가한 경우

EXLAIN SELECT * FROM PostBox WHERE Id > 500;
  • 인덱스 레인지 스캔
    • 인덱스 레인지 스캔은 데이터를 읽기 위해 주로 랜덤 I/O를 사용
    • 풀 테이블 스캔은 순차 I/O를 사용
      • 큰 테이블의 레코드 대부분을 읽는 작업에서는 인덱스를 사용하지 않고 풀 테이블 스캔을 사용하도록 유도할 때도 있다.


결론


  • * 을 사용하면 테이블을 풀 스캔 할 확률이 올라간다.
  • * 을 사용한다고 무조건 테이블을 풀 스캔 하는 것은 아니다.
  • * 을 사용한다고 해도 WHERE 절에 Index 칼럼의 적절한 범위를 SELECT하면 쿼리 성능 저하를 피할 수 있다.


참고 자료


  • 블로그 어제보다 오늘 더 - [SQL] SELECT * 쓰지 말자 => 링크
  • [TIP]MSSQL 와일드 카드를 이용한 검색과 주의점 => 링크
  • 7 Reasons Why Using SELECT * FROM TABLE in SQL Query Is a Bad Idea => 링크
  • 블로그 기억보단 기록을 - 1. 커버링 인덱스 (기본 지식 / WHERE / GROUP BY) => 링크
profile
기술에 대한 고민과 배운 것을 회고하는 게임 서버 개발자의 블로그입니다.

0개의 댓글