• 티스토리 홈
  • 프로필사진
    31514
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
31514
  • 프로필사진
    31514
    • 분류 전체보기 (110)
      • Book (66)
        • Learning SQL (9)
        • SQL 레벨업 (8)
        • 견고한 데이터 엔지니어링 (5)
        • 운영체제 (2)
        • 스파크 완벽 가이드 (9)
        • 파이썬 코딩의 기술 (29)
        • 분산 컴퓨팅 (4)
      • 개발 (26)
      • 기타 (10)
        • 출퇴근 공부 간단 정리 (7)
      • ELK (6)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    • 최근 공지
      • 31514의 이전 블로그는 여기로!
      등록된 공지가 없습니다.
    # Home
    # 공지사항
    #
    # 태그
    # 검색결과
    # 방명록
    • 8장 - SQL의 순서
      2024년 09월 27일
      • 31514
      • 작성자
      • 2024.09.27.오후04:18

      프로그래밍을 할 때, 특정 순서를 가진 데이터를 다루는 일이 자주 있다.

      그런데 SQL은 전통적으로 순번을 다루기 위한 기능을 가지고 있지 않다.

      하지만 실제로는 레코드에 적당한 순번을 붙여야 하는 경우가 많은데, 최근 SQL은 순서와 순번을 다루기 위한 기능들을 추가하고 있다.

      결과적으로 현대의 SQL은 전통적인 집합 지향적 성향에 절차 지향적 생각이 섞인, 하이브리드 언어로 변화하고 있다.

      레코드에 순번 붙히기

      레코드에 순번을 붙이는 방법은 크게 두 가지가 있다.

      윈도우 함수를 사용하는 방법과 상관 서브쿼리를 사용하는 방법인데, 보통 윈도우 함수의 성능이 더 좋고 가독성도 뛰어나기 때문에 여기서는 윈도우 함수 예시만 보여준다.

      select student_id,
             row_number() over (order by student_id) seq
      from weights;

      순번을 이용한 중앙값 구하기

      -- 무게의 중앙값 찾기
      select avg(weight) median
      from (select weight,
                   row_number() over (order by weight, student_id) hi
                   row_number() over (order by weight desc, student_id desc) lo
            from weights) tmp
      where hi in (lo, lo - 1, lo +1);

      weigth 컬럼을 오름차순으로 번호를 붙이고, 내림차순으로 번호를 붙인 뒤에 같은 순번을 가지고 있는 열이나 값의 차이가 1인 열을 찾는 쿼리다.

      그런데 왜 student_id도 같이 정렬하는 것일까?

      만약 무게가 같은 학생들이 있다면 정렬의 기준이 동일하다고 확신할 수 없기 때문이다.

       

      여기서 성능을 더 향상시키고 싶다면, 정렬이 2번 사용되는 이슈를 1번으로 줄일 수 있지만 생각해내기 어려운 거 같다.

      select avg(weight)
      from (select weight,
                   2 * row_number() over (order by weight)
                     - count(*) over() as diff
            from weights) tmp
      where diff between 0 and 2;

      순번을 이용한 테이블 분할

      +------+
      | num  |
      +------+
      |    1 |
      |    3 |
      |    4 |
      |    7 |
      |    8 |
      |    9 |
      |   12 |
      +------+

      위와 같은 테이블이 있을 때, 연속성이 끊긴 부분을 보여주는 테이블을 만든다고 해보자.

       

      <집합 지향적 방법>

      select (n1.num + 1) gap_start,
             '~',
             (min(n2.num) - 1) gap_end
      from numbers n1
      inner join numbers n2 on n2.num > n1.num
      group by n1.num
      having (n1.num + 1) < min(n2.num);

      이 쿼리문으로 다음과 같은 결과를 만들 수 있다.

      +-----------+---+---------+
      | gap_start | ~ | gap_end |
      +-----------+---+---------+
      |         2 | ~ |       2 |
      |         5 | ~ |       6 |
      |        10 | ~ |      11 |
      +-----------+---+---------+

      하지만 Nested Loops 결합이 일어나, 비용이 높고 실행 계획 변동 위험을 유발한다.

       

      <절차 지향적 방법>

      select num + 1 as gap_start,
             '~',
             (num + diff - 1) gap_end
      from (select num,
                   (max(num) over (order by num rows between 1 following and 1 following) - num) diff
                   from numbers) tmp
      where diff != 1;

      이는 테이블에 1회 접근하고, 윈도우 함수에서 정렬이 실행되며, 결합을 사용하지 않기 때문에 성능이 안정적이다.

      특이한 점은 SQL 레벨에서 보면, 집합 지향적 방법에서는 Nested Loops 반복이 사용되었는데, 절차 지향적 방법은 반복이 사용되지 않는다.

       

      순번을 다루는 또 다른 방법 - 시퀀스 객체

      일단 시퀀스 객체는 최대한 사용하지 않는 것이 좋다.

       

      시퀀스 객체는 '객체'라는 용어에서 알 수 있듯이 테이블 또는 뷰처럼 스키마 내부에 존재하는 객체 중 하나이다.

      create sequence testseq
      start with 1
      increment by 1
      maxvalue 100000
      minvalue 1
      cycle;

       

      <시퀀스 객체의 성능 문제>

      시퀀스 객체는 유일성, 연속성, 순서성을 보장하기 위해 락 메커니즘이 필요하다.

      따라서 여러 사용자가 시퀀스 객체에 접근하는 경우 락 충돌로 인해 성능 저하 문제가 발생한다.

       

      두 번째로 핫스팟과 관련된 문제다.

      핫스팟은 순번처럼 비슷한 데이터를 연속으로 삽입하는 경우 물리적으로 같은 영역에만 저장되기 때문에 I/O 부하가 커지는 것을 말한다.

      'Book > SQL 레벨업' 카테고리의 다른 글

      10장 - 인덱스 사용  (0) 2024.10.04
      9장 - 갱신과 데이터 모델  (2) 2024.09.30
      7장 - 서브쿼리  (1) 2024.09.25
      6장 - 결합  (0) 2024.09.24
      5장 - 반복문  (0) 2024.09.23
      다음글
      다음 글이 없습니다.
      이전글
      이전 글이 없습니다.
      댓글
    조회된 결과가 없습니다.
    스킨 업데이트 안내
    현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
    ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
    목차
    표시할 목차가 없습니다.
    • 레코드에 순번 붙히기
    • 순번을 이용한 중앙값 구하기
    • 순번을 이용한 테이블 분할
    • 순번을 다루는 또 다른 방법 - 시퀀스 객체
    • 안녕하세요
    • 감사해요
    • 잘있어요

    티스토리툴바

    단축키

    내 블로그

    내 블로그 - 관리자 홈 전환
    Q
    Q
    새 글 쓰기
    W
    W

    블로그 게시글

    글 수정 (권한 있는 경우)
    E
    E
    댓글 영역으로 이동
    C
    C

    모든 영역

    이 페이지의 URL 복사
    S
    S
    맨 위로 이동
    T
    T
    티스토리 홈 이동
    H
    H
    단축키 안내
    Shift + /
    ⇧ + /

    * 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.