현업의 그 누구도 여러분께 "Item 테이블에 ItemSizeCd가 REG이면서 ItemCat가 BEV인 데이터만 보여주세요." 라고 친절하게 요청하지 않을 겁니다. 우리는 현업의 언어를 이해하기 위해 데이터를 이해해야 합니다.

 

 

  • StartUP SQL 교육 슬라이드를 책으로 작성 중인 페이지입니다.
    • StartUP SQL이란? 데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육입니다.
    • 전체 교육 슬라이드는 무료 오픈되어 있습니다: https://sweetquant.tistory.com/497

 

 

 

데이터 이해하기

SQL을 작성하는 이유는 데이터를 조회하거나 조작(변경, 입력, 삭제)하기 위해서입니다. 간단히 말하면 데이터를 다루기 위해 SQL을 사용합니다. 단지 SQL을 배우는 목적이 아니라 데이터를 다루기 위해 SQL을 배우는 것입니다.

그런데 우리는 우리가 다루어야 할 데이터에 대해 얼마나 알고 있나요?

많은 분들이 SQL만 배우면 취업이 되고 일하는데 문제가 없을거라고 생각합니다.

하지만, 실제 업무를 해보면 SQL 기술보다 중요한 것이 데이터를 아는 것입니다.

은행, 보험, 병원과 같은 특화된 업무일수록 더욱 데이터 이해를 필요로 합니다.

해당 업종의 취업 공고를 보면 경험자를 찾는 것을 어렵지 않게 볼 수 있습니다.

SQL을 활용해 기계적으로 데이터를 추출하는 일은 많은 사람들이 할 수 있습니다.

다른 사람들보다 조금 더 앞서 나가기 위해서는 SQL뿐만 아니라 데이터를 이해해야 합니다.

그리고 데이터를 이해하고 나면, SQL이 더 쉬워집니다.

SQL 교육을 해보면 개발자보다 업무 지식이 있거나, 데이터에 대한 이해가 빠른 사람들이 SQL을 잘 만드는 것을 자주 볼 수 있습니다.

 

데이터 이해하기 4단계.

바로 앞에서는 테이블 설계, 식별자, PK에 대해 이야기했습니다. 이것들은 데이터 이해를 위해 필요한 아주 기초적인 지식입니다. 이제 본격적으로 데이터 이해를 위해 테이블을 직접적으로 살펴볼 시간입니다.

데이터를 이해하기 위해서는 절대적인 경험과 시간이 필요합니다. 여기서 소개하는 방법으로 데이터를 완벽히 이해할수는 없습니다. 다만, 이 방법들을 통해 데이터와 조금 더 친숙해질 수 있으며, 결국 데이터를 조금 더 빨리 이해하는데 도움이 될 것입니다.

데이터 이해를 위해 아래와 같은 4 단계의 작업을 권장합니다. 순서상 4번을 가장 마지막에 놓았지만 4번은 언제 진행해도 상관없습니다. 1번과 4번을 병행하는 것도 좋은 방법입니다.

  1. ERD와 실제 데이터 살펴보기.
  2. ERD에서 관계 테이블 살펴보기
  3. 코드성 데이터 추적하기
  4. 자료형 살펴보기

​위 4단계로 Item(상품) 데이터를 이해해보도록 하겠습니다.

1. ERD와 실제 데이터 살펴보기 - Item(상품) 테이블

데이터 이해를 위해 가장 먼저 할 일은 아래와 같이, ERD와 실제 저장된 데이터를 조회하는 것입니다.

 

ERD로 테이블의 각 컬럼이 의미하는 바를 확인하고, 데이터를 통해 각 컬럼별로 어떤 값들이 있는지 살펴봅니다. 그리고 컬럼별로 자신의 생각을 정리합니다. 이것만으로 데이터와 한층더 가까워집니다. 살펴본 내용을 아래와 같이 정리해봅니다.

  • ItemId: 상품(Item)을 구별하는 식별자, PK 컬럼이다.
  • ItemNm: 상품의 전체 명칭 값이 들어가 있음
  • ItemCat: 상품카테고리, COF, BKR과 같은 값이 있음
    • 해당 값 들의 의미를 좀 더 조사해볼 필요가 있음
  • ItemSizeCd: 상품의 사이즈를 나타내는 코드
    • BIG과 REG가 있음, REG는 Regular 같음
  • HotColdCd: Hot/Cold 구분을 나타내는 코드. 실제 값도 HOT 아니면 COLD
  • LaunchDt: 상품이 출시한 일자

이처럼 자신만의 생각으로 컬럼이 의미하는 바를 정리해보기 바랍니다. 그리고 PK 컬럼이 무엇인지 반드시 기억해두기 바랍니다. PK 컬럼은 나중에 조인에도 자주 사용되며, 데이터를 정확히 처리하기 위해 반드시 필요한 속성입니다.
이와 같은 정리가 틀렸을 수도 있습니다. 틀리더라도 정리를 해보는 것이 중요하며 나중에 틀린 점은 하나씩 바로 잡으면 됩니다. 업무 담당자나 개발자, 선배 등에게 질문이 필요한 내용은 잘 체크해놓고 기회가 있을 때 질문하면 됩니다.
​​

2. ERD에서 관계 테이블 살펴보기

ERD를 살펴보면, Item 테이블과 관계선으로 연결된 테이블을 발견할 수 있습니다. 아래와 같이 Item(상품) 테이블과, ItemCat(상품카테고리), ItemPrcHist(상품가격이력), OrdDet(주문상세) 테이블이 연결되어 있습니다. 이를 통해 Item 테이블이 아래 테이블들과 관련이 있구나 정도만 기억해도 성공입니다.

 


관계에 대해 정확히 이해하기 위해서는 관계선과 관계차수에 대한 이해가 필요한데, 아직은 이 부분은 이해하지 못해도 괜찮습니다. 안타깝게도 ERD에 이와 같은 관계선 자체가 없는 경우도 실제로 많답니다.
관계 있는 테이블을 하나씩 조회해보면서 데이터를 살펴보며, 어떤 정보가 있는지 살펴봅니다. 이는 나중에 데이터를 확장해서 분석하는데 큰 도움이 됩니다.
테이블을 하나씩 조회하다 보면 ItemCat(상품카테고리) 테이블에 BEV, BKR과 같은 값의 의미가 저장된 것을 알 수 있습니다. 이 값은 Item(상품) 테이블에 ItemCat 컬럼에도 있던 내용입니다. ItemCat 테이블을 통해 BEV가 무엇인지, BKR이 무엇인지 확인할 수 있다는 것을 알 수 있습니다.

SELECT  T1.*
FROM    startdb.ItemCat T1;

-- 결과
ItemCat  ItemCatNm  
-------  ---------  
BEV      음료       
BKR      베이커리   
COF      커피

 

3. 코드성 데이터 추적하기

시스템을 설계하면 다양한 코드성 데이터가 정의됩니다.

코드성 데이터는 기준코드(공통코드, 기초코드, 기본코드등 다양한 이름으로 불립니다. 여기서는 기준코드란 이름을 사용하겠습니다.)란 테이블을 만들어  관리하는 것이 일반적입니다.

대부분의 업무 프로세스의 상태나 유형들은 코드화되서 관리되며, 이러한 코드에 따른 값들이 기준코드 테이블 안에 데이터로 관리됩니다.

처음으로 접한 데이터베이스라면 이 기준코드 테이블 명이 무엇인지 빨리 파악해 놓으면 좋습니다.

그리고 중요한 코드 몇 개 외워놓는 것도 앞으로 데이터를 활용하는데 큰 도움이 됩니다.

 

우리가 실습 중인 데이터베이스에는 BaseCdDv(기준코드구분)와 BaseCd(기준코드) 테이블에 코드성 데이터의 정보가 담겨있습닙다. BaseCdDv는 기준코드의 종류를 정의하기 위한 부모 테이블로, 실제 기준코드에 따른 값은 BaseCd 테이블만 확인하면 됩니다. BaseCdDv와 BaseCd 테이블은 아래와 같은 구조입니다.

 

 

우리가 사용 중인 startdb의 테이블들에는 기준코드 사용 규칙이 있습니다. 기준코드로 등록된 값을 가지게 되는 컬럼은, 컬럼명 자체를 기준코드구분(BaseCdDv) 값으로 사용합니다. 그러므로 Item(상품) 테이블에 ItemSizeCd(상품사이즈코드)란 컬럼의 코드 데이터들을 확인하고 싶다면, 아래와 같이 BaseCd 테이블에 BaseCdDv 조건으로 ItemSizeCd를 사용하면 됩니다. 아래 SQL의 결과를 통해 ItemSizeCd에는 BIG과 REG란 코드 값이 있고 그에 따라 언어(LangDvCd)별로 코드 명을 관리하는 것을 알 수 있습니다.

SELECT  T1.*
FROM    startdb.BaseCd T1
WHERE   T1.BaseCdDv = 'ItemSizeCd';

BaseCdDv    BaseCd  LangDvCd  BaseCdNm      SortOrder  
----------  ------  --------  ------------  ---------  
ItemSizeCd  BIG     EN        Big Size      2          
ItemSizeCd  BIG     KR        큰 사이즈     2          
ItemSizeCd  REG     EN        Regular Size  1          
ItemSizeCd  REG     KR        기본 사이즈   1

 

Item(상품) 테이블의 HotColdCd 컬럼에 대한 코드와 한글 코드명만 알고 싶다면 아래와 같이 조회를 해보면 됩니다.

SELECT  T1.*
FROM    startdb.BaseCd T1
WHERE   T1.BaseCdDv = 'HotColdCd'
AND     T1.LangDvCd = 'KR';

BaseCdDv   BaseCd  LangDvCd  BaseCdNm  SortOrder  
---------  ------  --------  --------  ---------  
HotColdCd  COLD    KR        차가운    2          
HotColdCd  HOT     KR        뜨거운    1

 

이와 같은 데이터를 구성하는 코드 데이터는 데이터를 집계하거나 추출하는 주요 조건으로 자주 사용됩니다. 업무 처리에도 자주 사용되는 조건입니다. 그러므로 주요 코드 데이터 몇 개 정도는 외우고 SQL을 작성하시면 조금 더 편하고 효율적으로 SQL을 작성할 수 있습니다.

​​

4. 자료형 살펴보기

마지막으로 DESC 명령어를 통해 테이블의 자료형을 살펴봅니다. Comment도 같이 보고 싶다면 DESC가 아닌 아래 SQL을 사용해 볼 수 있습니다. 이 과정을 통해 각 컬럼별로 어떤 자료형을 사용하고 있는지 익혀두는 것입니다.

SELECT  T1.TABLE_SCHEMA DB ,T1.TABLE_NAME Tab
        ,T1.COLUMN_NAME Col ,T1.COLUMN_COMMENT Cmt
        ,T1.ORDINAL_POSITION Pos ,T1.COLUMN_TYPE Typ
        ,T1.IS_NULLABLE Null_YN ,T1.COLUMN_KEY Ky
FROM    INFORMATION_SCHEMA.COLUMNS T1
WHERE   T1.TABLE_NAME = 'Item'
AND     T1.TABLE_SCHEMA = 'startdb'
ORDER BY pos ASC;

-- 결과
DB       Tab   Col         Cmt                 Pos  Typ           Null_YN  Ky   
-------  ----  ----------  ------------------  ---  ------------  -------  ---  
startdb  item  ItemId      상품ID              1    varchar(40)   NO       PRI  
startdb  item  ItemNm      상품명              2    varchar(100)  YES           
startdb  item  ItemCat     상품카테고리        3    varchar(40)   YES      MUL  
startdb  item  ItemSizeCd  상품사이즈코드      4    varchar(40)   YES           
startdb  item  HotColdCd   아이스/HOT구분코드  5    varchar(40)   YES           
startdb  item  LaunchDt    출시일자            6    date          YES

 

4번 단계는 1단계 과정에서 같이 작업하는 것도 좋습니다. 대부분의 컬럼이 VARCHAR 형태의 문자형 데이터인 것을 알 수 있습니다. 출시일자인 LaunchDt만 DATE 자료형인 것을 인지하고 있으면 될거 같습니다.

 


네 단계를 거쳐 Item 테이블을 살펴봤습니다. 이 과정을 통해 Item 데이터와 좀 더 가까워졌기 바랍니다.

Item 데이터와 충분이 가까워졌다면, 이제 현업이 아래와 같이 요구하는 것을 알아 들을 수 있을 겁니다.

음료 상품 중에서 레귤러 사이즈의 상품만 보여주세요.

 

현업의 그 누구도 여러분께 "Item 테이블에 ItemSizeCd가 REG이면서 ItemCat가 BEV인 데이터만 보여주세요." 라고 친절하게 요청하지 않을 겁니다. 우리는 데이터를 이해하고 현업의 언어를 번역해 데이터를 추출하거나 분석해야 합니다.

 


[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

 

PK는 데이터의 정확성과 활용에 지대한 영향을 줍니다. PK를 정하기 위해 고민과 고민을 거듭해야 합니다.
이러한 고민의 시간은 자신의 성장에 큰 도움이 될 것이며, PK 선정을 위해 고심한 시간은 전혀 아깝지 않습니다

 

 

  • StartUP SQL 교육 슬라이드를 책으로 작성 중인 페이지입니다.
    • StartUP SQL이란? 데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육입니다.
    • 전체 교육 슬라이드는 무료 오픈되어 있습니다: https://sweetquant.tistory.com/497

지금까지 아주 간단한 SELECT 기초에 대해 익혔습니다.

진도를 더 나가기 전에 약간 원론적이지만 중요한 부분을 살펴보고 넘어가야 합니다.

바로 우리가 활용할 데이터를 이해하는 방법입니다.

 

 

데이터 이해하기 - 식별자와 PRIMARY KEY

MySQL, ORACLE, PostgreSQL과 같은 DBMS에서 SQL로 다루는 데이터는 관계형 데이터입니다.

여기서 관계(Relation)란 데이터를 행과 열로 조직화한 구조를 의미합니다. 즉, 테이블을 말합니다.

 

테이블은 관계형 데이터 모델 개념을 사용해 설계됩니다.

관계형 데이터 모델링은 데이터 활용 능력 발전에 매우 중요한 기술입니다.

SQL로 데이터를 활용할 수 있지만, 그 전에 제대로 된 테이블 구조에 데이터가 저장되어 있어야 합니다.

테이블 구조에 따라 SQL 작성 방법이 달라집니다. 또한 테이블 구조에 문제가 있으면 정확한 데이터 추출이 불가능할 수도 있습니다.

그러므로 SQL에 대한 공부가 어느 정도 마무리되었다면, 관계형 데이터 모델링 공부에 시간을 투자해보시기 바랍니다.

제대로 데이터를 쌓아야, 제대로 데이터를 활용할 수 있으니까요.

나중에는 SQL만 공부한 사람과 SQL과 데이터 모델링을 모두 공부한 사람간의 데이터 활용 능력은 매우 큰 차이가 날 수 있습니다.

테이블 설계 과정을 아주 간단하게 살펴보고 넘어가도록 하겠습니다.
관계형 데이터 모델은 개념 설계, 논리 설계, 물리 설계의 세 단계로 이루어집니다.

  • 개념 설계: 관리할 데이터의 핵심적인 개념만 정리해서 표현합니다. 주로 엔티티명(논리 테이블명)과 식별자 정도를 정의합니다.
  • 논리 설계: 개념 설계를 좀 더 상세화합니다. 엔티티(논리 테이블명)에 필요한 모든 속성(컬럼의 논리명)을 도출합니다.
  • 물리 설계: 논리 설계의 결과를 실제 구현할 DBMS에 맞게 설계하는 과정입니다.

 

실제 프로젝트를 해보면, 논리 설계와 물리 설계를 분리해 진행하는 경우는 드뭅니다.

다양한 이유로 논리 설계와 물리 설계가 동시에 이루어지는 경우가 많습니다.

관계 데이터를 설계하는 과정에서 중요한 개념 중 하나로 정규화(Normaliztion)가 있습니다.
개념 설계부터 물리 설계까지 항상 정규화를 유념해서 설계를 진행하게 됩니다.
(여기서는 정규화에 대해 별도 설명하지 않습니다. 매우 긴 내용이니까요.)

관계형 데이터 모델 기법을 이용해 테이블을 설계할 때는 ERD(Entity-Relation-Diagram) 툴을 사용합니다.

대표적인 툴로 ERWIN이 있으며, 우리나라에서는 DA#도 많이 사용됩니다. 안타깝게도 유료툴입니다.

개인 연습용으로 ERD를 그려보고 싶다면 ERD-CLOUD와 같은 웹상의 무료 플랫폼도 있으니 참고하시기 바랍니다.

ERD 툴로 설계된 상품 테이블과 실제 저장된 상품 데이터를 비교해보면 아래와 같습니다.

 


테이블에서 데이터를 조회하면 위 그림의 오른쪽과 같이 컬럼이 가로로 펼쳐지고 저장된 값들이 위에서 아래로 출력됩니다. 그런데, ERD Tool로 테이블을 설계할 때는 그림 왼쪽과 같이 컬럼을 위에서 아래로 채워가면서 세로로 표시합니다.

이처럼 컬럼을 세로로 나열해야 더 많은 테이블을 효율적으로 설계할 수 있습니다.

테이블 설계 과정에서 가장 중요한 것 하나를 뽑으라면 바로 PK(Primary Key)입니다.

PK를 이해하려면 식별자(Identifier)에 대해서 먼저 알아야 합니다.​
식별자는 데이터를 식별할 수 있는 속성(컬럼)을 뜻합니다. 데이터를 식별할 수 있다는 것은, 데이터 집합에서 한 건의 데이터만 정확히 골라낼 수 있다는 뜻이기도 합니다.

 

A 대학교에 재학 중인 학생 데이터 집합의 식별자로 학번을 사용할 수 있습니다.

한 학교내에서 학번은 중복되지 않습니다. 9627015란 학번을 가진 학생이 두 명 이상 존재할 수 없는 것이죠.

그러므로 학번을 이용하면 정확히 한 명의 학생만 찾아낼 수 있습니다.

이처럼 데이터를 구분해 한 건을 정확히 골라낼 수 있는 속성을 식별자라고 합니다.

우리가 코인 노래방에서 원하는 노래를 정확히 선택해서 부르려면 노래 번호를 입력해야 합니다.

노래 번호가 노래의 식별자가 되는 것이죠.

하나의 데이터 집합은 여러 개의 식별자가 있을 수 있습니다.

다시 학생 데이터 집합으로 돌아가보죠.

학번 외에도 주민등록번호, 이메일, 핸드폰 번호도 식별자로 사용할 수 있습니다.

또한 식별자는 여러 속성을 결합해서 정의할 수도 있습니다.

학생이 수업을 신청한 "수강신청"이라는 데이터 집합은 "학번, 과목, 학기"(예: 2023년 1학기, 2023년 2학기) 세 개의 속성을 결합해 식별자로 사용할 수 있습니다.

식별자에 대해 정리해보면 아래와 같습니다.

  • 식별자는 데이터 집합(테이블)에서 데이터 한 건을 유일하게 식별해 낼 수 있는 속성이다.
  • 식별자는 데이터 집합별로 여러 개 있을 수 있다.
  • 하나의 식별자는 여러 속성(컬럼)을 결합해 사용할 수 있다.

​지금까지 식별자를 열심히 설명한 이유는 PK(Primary Key)를 설명하기 위함이었습니다.
그런데 식별자를 이해했다면 PK를 이미 이해한 것과 같습니다. PK는 데이터 집합의 여러 식별자 중에서 대표로 사용하는 식별자이니까요.

예를 들어, 학생의 식별자로 학번, 주민등록번호, 이메일, 핸드폰 번호가 있는데, 이 중에 대표 식별자 하나를 정합니다.

이 대표 식별자가 테이블 생성 시 바로 PK 속성(제약 조건)으로 지정됩니다.

대표 식별자는 데이터 집합을 가장 잘 표현할 수 있으며, 변경되지 않으며, 노출 시 보안에 문제가 없는 속성을 사용하는 것이 좋습니다.

이외에도 다양한 부분을 고려해 대표 식별자를 정하게 됩니다.

학생 데이터 집합의 대표 식별자로는 학번이 가장 적절합니다. 따라서 학생 테이블의 PK로 학번이 선정됩니다.

앞에서 "테이블 설계 과정에서 가장 중요한 것 하나를 뽑으라면 바로 PK(Primary Key)입니다."라고 언급했습니다.

데이터를 활용하려면 데이터의 정확성이 뒷받침되어야 합니다.

데이터의 정확성을 위해서는 중복된 데이터가 있어서는 안됩니다. 이를 보장하기 위해 필요한 최소한의 장치가 바로 PK입니다.

데이터를 활요하기 위해서는 필요한 데이터를 정확히 찾아 낼 수 있어야 합니다. 이를 위해 사용하는 대표적인 조건 속성도 PK 컬럼입니다.

또한 데이터를 보다 다채롭게 활용하기 위해서는 데이터와 데이터를 연결해야 합니다. 일반적으로 데이터 연결을 위해 사용하는 조건 컬럼이 바로 PK와 FK 컬럼입니다. PK 컬럼 정의에 따라 데이터 연결이 쉬워질 수도 있고 복잡해 질 수도 있습니다.

이처럼 PK는 데이터의 정확성과 활용에 지대한 영향을 줍니다. PK를 정하기 위해 고민과 고민을 거듭해야 합니다.

이러한 고민의 시간은 자신의 성장에 큰 도움이 될 것이며, PK 선정을 위해 고심한 시간은 전혀 아깝지 않습니다.

 

오늘은 여기까지입니다. 감사합니다.



[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

 

  • StartUP SQL 교육 슬라이드를 책으로 작성 중인 페이지입니다.
    • StartUP SQL이란? 데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육입니다.
    • 실습을 위한 환경 설정 참고: https://sweetquant.tistory.com/561
 

[StartUP SQL BOOK]실습 환경 구성하기

StartUP SQL 교육 슬라이드를 책으로 작성 중인 페이지입니다.StartUP SQL이란? 데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육입니다.현재 블로그에 전체 교육 슬라이드 무료로 오픈되어 있습니

sweetquant.tistory.com

 

 

 

별칭

SQL을 작성할 때 테이블과 컬럼에 별칭을 지정할 수 있습니다. 이와 같은 별칭은 SQL의 가독성을 높여주고, SQL 작성을 조금 더 효율적으로 할 수 있게 해줍니다.

 

 

테이블 별칭

FROM 절의 테이블에 테이블 별칭을 정의할 수 있습니다. 아래는 FROM 절의 상품(Item) 테이블을 T1이란 별칭으로 정의한 SQL입니다.

SELECT  ItemId ,ItemNm ,ItemCat
FROM    startdb.Item T1
WHERE   ItemNm LIKE '아이스%'
ORDER BY ItemId ASC;

 

테이블 별치을 정의할 때는 아래와 같이 as를 사용할 수도 있습니다.

SELECT  ItemId ,ItemNm ,ItemCat
FROM    startdb.Item as T1
WHERE   ItemNm LIKE '아이스%'
ORDER BY ItemId ASC;

 

이처럼 정의한 테이블 별칭은 SELECT, WHERE, ORDER BY 절의 컬럼명 앞에 붙여서 사용할 수 있습니다. 아래 SQL을 보면 컬럼명 앞에 테이블 별칭인 T1을 붙여서 사용하고 있습니다. 

SELECT  T1.ItemId ,T1.ItemNm ,T1.ItemCat
FROM    startdb.Item T1
WHERE   T1.ItemNm LIKE '아이스%'
ORDER BY T1.ItemId ASC;

 

이와 같이 SQL을 작성하면 SELECT 절의 ItemId가 FROM 절의 T1(Item)의 컬럼이란 것을 명확히 표시해줄 수 있습니다.

사실, 지금처럼 FROM 절에 하나의 테이블만 있는 경우에는 테이블 별칭을 사용하지 않아도 됩니다.
SQL에 사용한 모든 컬럼이 FROM 절의 테이블에 존재한다는 것을 SQL 작성자나 MySQL이나 다 알기 때문이죠.
하지만, 앞으로 우리가 배울 JOIN 이 포함된 SQL은 FROM 절에 여러 개 테이블이 사용됩니다.

JOIN과 같이 FROM 절에 여러 테이블을 사용하면 테이블 간에 같은 컬럼명이 중복 존재할 수 있습니다.

이때, 테이블 별칭으로 컬럼이 어느 테이블에 속하는지를 지정해주지 않으면 SQL 자체가 에러로 실행되지 않을 수 있습니다. 


Tip. JOIN

JOIN(조인)은 테이블을 연결하는 구문으로서 관계형 데이터를 다루는 매우 중요한 핵심 기능입니다. 더 뒤에서 조인에 대해 배우게 될 것입니다.


 

아래 SQL을 실행해보면 에러가 발생합니다. 조인에 참여하는 상품(Item)과 상품가격이력(ItemPrcHist) 모두에 ItemId 컬럼이 존재하는데 SELECT 절에서 ItemId가 어느 테이블에 속하는지 명시하지 않아 에러가 발생한 것입니다.

SELECT  ItemId ,ItemNm ,ItemCat, ToDt, SalePrc
FROM    startdb.Item T1
        INNER JOIN startdb.ItemPrcHist T2
            ON (T1.ItemId = T2.ItemId)
WHERE   T1.ItemNm LIKE '아이스%'
ORDER BY ItemId ASC;

-- 에러
Column 'ItemId' in field list is ambiguous

 

위와 같은 에러를 피하려면 SQL에서 컬럼명을 사용할 때 '테이블별칭.컬럼'과 같이 작성해야 합니다. 아래와 같이 말이죠.

SELECT  T1.ItemId ,T1.ItemNm ,T1.ItemCat, T2.ToDt, T2.SalePrc
FROM    startdb.Item T1
        INNER JOIN startdb.ItemPrcHist T2
            ON (T1.ItemId = T2.ItemId)
WHERE   T1.ItemNm LIKE '아이스%'
ORDER BY T1.ItemId ASC;

 

가능하다면 FROM 절에 하나의 테이블만 있어도 테이블 별칭을 정의하고 '테이블별칭.컬럼명'과 같이 SQL을 작성하는 것이 좋습니다. SQL을 작성하다 보면 처음에 하나의 테이블만 사용하다가 조인이 추가되는 경우가 많기 때문이죠.

 

컬럼 별칭

SELECT 절에서는 컬럼명 뒤에 컬럼 별칭을 지정할 수 있습니다. 컬럼명은 테이블을 생성할 때 정의한 물리적인 명칭입니다. 이러한 물리적인 명칭을 데이터 조회 시점에는 다른 명칭으로 보여주어야 할 때가 있습니다. 이때 컬럼 별칭을 지정할 수 있습니다.
아래 SQL은 ItemId 컬럼을 상품ID로, ItemNm은 상품명으로 별칭 처리한 SQL입니다.

SELECT  T1.ItemId 상품ID ,T1.ItemNm 상품명
FROM    startdb.Item T1
WHERE   T1.ItemId = 'IAMB'
ORDER BY T1.ItemId ASC;

-- 결과
상품ID  상품명                  
------  -------------------  
IAMB    아이스아메리카노(B)

 

컬럼의 별칭을 정의할 때도 as 키워드를 사용할 수 있습니다.

SELECT  T1.ItemId as 상품ID ,T1.ItemNm as 상품명
FROM    startdb.Item T1
WHERE   T1.ItemId = 'IAMB'
ORDER BY T1.ItemId ASC;


정의된 컬럼의 별칭은 아래와 같이 WHERE 절에서는 사용할 수 없습니다.

SELECT  T1.ItemId 상품ID ,T1.ItemNm 상품명
FROM    startdb.Item T1
WHERE   상품ID = 'IAMB'
ORDER BY T1.ItemId ASC;

-- 에러
Unknown column '상품ID' in 'where clause'

 

아마도 DBMS(MySQL) 내부적으로 SELECT 절의 별칭 정의보다 WHERE 절을 먼저 처리하기 때문인거 같습니다.

실제 DBMS 내부적으로도 이와 같은 순서로 처리되는지는 알 수 없습니다. 다만, WHERE 절에서 SELECT 절의 별칭을 사용할 수 없다는 점으로 유추해볼 뿐입니다.

 

컬럼 별칭과 백틱

컬럼 별칭에 특수문자가 포함되거나 컬럼별칭을 숫자로 시작해야 할 경우에는 백틱(`)을 사용해 별칭을 정의해야 합니다.
백틱은 키보드의 Tab 키 위에, ESC키 아래 물결(~)과 함께 있는 키입니다.
백틱(`)은 MySQL에서 주로 사용됩니다. 오라클의 경우는 더블따옴표("")를 사용해 특수 문자가 포함된 컬럼 별칭을 정의합니다.
아래 SQL은 '핫/콜드구분' 별칭에 특수문자인 '/' 가 포함되어 에러가 발생합니다.

SELECT  T1.ItemId 상품ID ,T1.ItemNm 상품명 ,T1.HotColdCd 핫/콜드구분
FROM    startdb.Item T1
WHERE   T1.ItemId = 'IAMB'
ORDER BY T1.ItemId ASC;

-- 에러
You have an error in your SQL syntax;


​위 SQL은 아래와 같이 백틱을 이용해 컬럼 별칭을 정의해야 합니다.

SELECT  T1.ItemId 상품ID ,T1.ItemNm 상품명 ,T1.HotColdCd `핫/콜드구분`
FROM    startdb.Item T1
WHERE   T1.ItemId = 'IAMB'
ORDER BY T1.ItemId ASC;

-- 결과
상품ID  상품명               핫/콜드구분       
------  -------------------  -----------  
IAMB    아이스아메리카노(B)  COLD


 

별칭을 사용한 ORDER BY

SELECT 절에서 정의된 컬럼 별칭은 WHERE 절에서는 사용할 수 없지만, ORDER BY 절에서는 사용할 수 있습니다.

아래 SQL은 컬럼 별칭을 사용해 ORDER BY를 처리하고 있습니다.

SELECT  T1.ItemId 상품ID ,T1.ItemNm 상품명
FROM    startdb.Item T1
WHERE   T1.ItemCat = 'BKR'
ORDER BY 상품ID ASC;


위 SQL의 ORDER BY는 아래와 같이 T1.ItemId를 바로 사용해도 됩니다.

SELECT  T1.ItemId 상품ID ,T1.ItemNm 상품명
FROM    startdb.Item T1
WHERE   T1.ItemCat = 'BKR'
ORDER BY T1.ItemId ASC;


마지막으로 ORDER BY 절에서는 SELECT 절의 컬럼 위치에 대한 순번을 사용할 수도 있습니다.
아래 SQL은 ORDER BY에 1이라고 표시했습니다. 여기서 1은 SELECT 절의 가장 왼쪽 컬럼인 T1.ItemId를 뜻합니다.

결국 앞에서 살펴본 두 개의 SQL과 같은 기준으로 정렬이 처리되는 SQL입니다.

SELECT  T1.ItemId 상품ID ,T1.ItemNm 상품명
FROM    startdb.Item T1
WHERE   T1.ItemCat = 'BKR'
ORDER BY 1 ASC;

 

별칭 사용법에 대해 살펴봤습니다. SQL을 작성할 때 별칭을 습관적으로 사용하는 것을 추천드립니다.

SQL이 길어지고 복잡해질수록 적절한 별칭이 있어야 작성도 쉬워지며 가독성도 높아집니다.

 

다 이해하셨다면, 간단한 퀴즈 풀고 넘어가세요.



[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

'SQL > StartUP SQL(교육슬라이드)' 카테고리의 다른 글

20-3. WINDOWING  (0) 2024.04.11
20-2. LAG와 LEAD  (0) 2024.04.11
20-1. PARTITION BY  (0) 2024.04.11
19-4. GROUP BY와 분석함수  (0) 2024.04.11
19-3. 순위 분석함수  (0) 2024.04.11
19-1~19-2. 분석함수 이해하기  (0) 2024.04.11
18. 날짜 테이블  (0) 2024.04.11
17. PIVOT  (0) 2024.04.11

 

  • StartUP SQL 교육 슬라이드를 책으로 작성 중인 페이지입니다.
    • StartUP SQL이란? 데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육입니다.
    • 전체 교육 슬라이드는 무료 오픈되어 있습니다: https://sweetquant.tistory.com/497


ORDER BY

ORDER BY 절은 조회 데이터의 정렬 순서를 결정합니다.

ORDER BY는 SELECT SQL의 가장 마지막에 사용합니다. ORDER BY 절 뒤로 정렬 기준으로 사용할 컬럼을 지정해 주면 됩니다.

아래와 같이 SQL을 실행해보면 상품명(ItemNm)의 순서로 데이터가 정렬되어 출력됩니다. 이때, ORDER BY 컬럼명 뒤에 특정한 기준을 정의하지 않으면 작은 값이 먼저 나오고 큰 값이 나중에 나오는 오름차순으로 정렬이 됩니다. 결과를 보면 ItemNm 값이 가장 작은 '레몬에이드'가 가장 먼저 나오고, 그 다음에는 그 다음으로 큰 값인 '마카롱'이 출력되어 있습니다. (문자의 정렬은 문자의 크기 순서로 이루어지는데 기본적으로 가나다 순서를 따릅니다. 그러므로 ㄹ이 앞에 있는 레몬에이드가 ㅁ이 앞에 있는 마카롱보다 작은 값이 됩니다.)

SELECT  ItemId ,ItemNm ,ItemCat
FROM    startdb.Item
ORDER BY ItemNm;

-- 결과
ItemId  ItemNm               ItemCat  
------  -------------------  -------  
LEMR    레몬에이드(R)        BEV      
MACA    마카롱(R)            BKR      
BGLR    베이글(R)            BKR      
BMFR    블루베리머핀(R)      BKR 
… 생략 …

 


데이터를 정렬하는 방법은 두 가지가 있습니다. 하나는 작은 값이 먼저 나오고 큰 값이 나중에 나오는 오름차순이고 다른 하나는 정 반대로 처리되는 내림차순입니다. 내림차순은 큰 값이 먼저 나오고 작은 값이 나중에 나옵니다.

출력되는 데이터를 오름차순하고 싶다면 ORDER BY의 컬럼명 뒤에 ASC 키워드를 내림차순하고 싶다면 DESC 키워드를 사용합니다.

위의 SQL과 같이 ASC, DESC를 명시하지 않으면 기본적으로 오름차순 처리됩니다.

아래는 상품명(ItemNm)을 내림차순 정렬해 데이터를 출력하는 SQL입니다. 상품명의 값이 가장 큰 핫초코(R)이 가장 먼저 출력된 것을 알 수 있습니다.

SELECT  ItemId ,ItemNm ,ItemCat
FROM    startdb.Item
ORDER BY ItemNm DESC;

-- 결과
ItemId  ItemNm               ItemCat  
------  -------------------  -------  
HCHR    핫초코(R)            BEV      
HCHB    핫초코(B)            BEV      
FLTR    플랫화이트(R)        COF      
CLR     카페라떼(R)          COF 
… 생략 …


여러 컬럼의 ORDER BY

ORDER BY 절에는 콤마를 사용해 여러 컬럼을 지정할 수 있습니다. ORDER BY에 여러 컬럼을 지정하면 가장 왼쪽 컬럼부터 차례대로 정렬이 처리됩니다.


​아래는 상품종류(ItemCat)가 BEV(음료), BKR(베이커리)인 데이터를 HotColdCd 컬럼으로 정렬하는 SQL입니다. 아직은 ORDER BY에 하나의 컬럼만 사용했습니다. ORDER BY HotColdCd에 정렬 방향을 지정하지 않았기 때문에 작은 값이 먼저 나오는 오름차순으로 결과가 출력됩니다.

SELECT  HotColdCd ,ItemId ,ItemNm ,ItemCat
FROM    startdb.Item
WHERE   ItemCat IN ('BEV','BKR')
ORDER BY HotColdCd;

-- 결과
HotColdCd  ItemId  ItemNm           ItemCat  
---------  ------  ---------------  -------  
COLD       CITR    유자에이드(R)    BEV      
COLD       LEMR    레몬에이드(R)    BEV      
COLD       ZAMB    자몽에이드(R)    BEV      
COLD       BMFR    블루베리머핀(R)  BKR      
COLD       CMFR    초코머핀(R)      BKR      
HOT        HCHB    핫초코(B)        BEV      
HOT        HCHR    핫초코(R)        BEV      
HOT        BGLR    베이글(R)        BKR      
HOT        MACA    마카롱(R)        BKR

 

 

결과를 보면, COLD인 상품이 먼저 출력되고 HOT인 상품이 나중에 출력되고 있습니다.

이번에는 위 SQL의 ORDER BY 절에 ItemId도 추가합니다. 아래와 같이 말이죠.

SELECT  HotColdCd ,ItemId ,ItemNm ,ItemCat
FROM    startdb.Item
WHERE   ItemCat IN ('BEV','BKR')
ORDER BY HotColdCd, ItemId;

-- 결과
HotColdCd  ItemId  ItemNm           ItemCat  
---------  ------  ---------------  -------  
COLD       BMFR    블루베리머핀(R)  BKR      
COLD       CITR    유자에이드(R)    BEV      
COLD       CMFR    초코머핀(R)      BKR      
COLD       LEMR    레몬에이드(R)    BEV      
COLD       ZAMB    자몽에이드(R)    BEV      
HOT        BGLR    베이글(R)        BKR      
HOT        HCHB    핫초코(B)        BEV      
HOT        HCHR    핫초코(R)        BEV      
HOT        MACA    마카롱(R)        BKR


​SQL 결과를 확인해보면, HotColdCd로 먼저 데이터가 정렬이 되어 있고, 같은 HotColdCd를 가진 데이터간에는 다시 ItemId로 정렬이 처리된 것을 알 수 있습니다. COLD인 상품들을 살펴보면, ItemId가 가장 작은 BMFR이 가장 먼저 나오고 그 다음에 CITR, CMFR, LEMR, ZAMB 순으로 정렬된 것을 알 수 있습니다.

ORDER BY HotColdCd와 ORDER BY HotColdCd, ItemId 에 따른 결과를 하나의 그림에 담아서 살펴보면 다음과 같습니다.

 

이처럼, ORDER BY에 여러 컬럼을 사용하면 가장 왼쪽의 컬럼 기준으로 먼저 정렬이 된 후에, 가장 왼쪽의 컬럼 값이 같은 데이터는 다시 두 번째 컬럼 기준으로 정렬이 됩니다.

 


Tip. 한 건의 레코드는 공동운명체

당연한 이야기이지만 누군가는 궁금해할지 모를 내용을 하나 말씀 드리면,
한 건의 레코드(로우)를 구성하는 컬럼의 값들이 ORDER BY로 인해 각각 다른 레코드로 분리되는 경우는 없습니다.
한 건의 레코드를 구성하는 값들은 공동운명체로서 언제나 같이 이동합니다.

물론 나중에 분석함수 등을 사용하면, 다른 레코드의 값을 현재의 레코드로 가져올 수는 있지만 기본적으로 한 건의 레코드는 공동운명체입니다.


 

이번에는 세 개 컬럼을 ORDER BY에 사용한 SQL입니다. 그리고 컬럼별로 정렬 방향의 기준을 지정했습니다.
가장 왼쪽에 있는 ItemCat로 먼저 오름차순 한 후에, 같은 ItemCat를 가진 레코드들은 HotColdCd로 내림차순 정렬됩니다.
그리고 같은 ItemCat와 HotColdCd를 가진 레코드는 다시 ItemId로 오름차순 정렬되어 결과가 출력됩니다.



ORDER BY에 관련된 간단한 BOOSTER QUIZ도 풀어보기 바랍니다. 쉽습니다.~!

퀴즈를 풀어보기 위한 실습환경 구성은 아래 글을 참고하세요.

https://sweetquant.tistory.com/561

 

[StartUP SQL BOOK]실습 환경 구성하기

StartUP SQL 교육 슬라이드를 책으로 작성 중인 페이지입니다.StartUP SQL이란? 데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육입니다.현재 블로그에 전체 교육 슬라이드 무료로 오픈되어 있습니

sweetquant.tistory.com

 

 



 

[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

 

 

  • StartUP SQL 교육 슬라이드를 책으로 작성 중인 페이지입니다.
    • StartUP SQL이란? 데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육입니다.
    • 전체 교육 슬라이드는 무료 오픈되어 있습니다: https://sweetquant.tistory.com/497
 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

 

 

특수 조건자

​WHERE 절에서 컬럼과 조건 값의 비교를 위해 =, >, <와 같은 비교 조건자를 지금까지 사용했습니다.

WHERE 절에는 조건 비교를 위해 BETWEEN, LIKE, IN과 같은 특수 조건자도 사용할 수 있습니다.

 

 

BETWEEN

BETWEEN 조건은 이상(>=)과 이하(<=) 조건을 동시에 처리할 수 있는 조건자입니다.

BETWEEN 뒤에는 '시작 조건값 AND 종료 조건값'과 같이 두 개의 조건 값을 줄 수 이습니다.

BETWEEN과 AND는 항상 쌍으로 사용됩니다. BETWEEN의 AND는 WHERE 절에서 조건을 연결하는 AND와는 별개입니다.

 

아래 예제를 살펴보시죠. 아래 예제는 Item(상품) 테이블에서 ItemId가 'A' 이상이면서 'C' 이하인 데이터를 조회하고 있습니다.

SELECT  ItemId ,ItemNm ,ItemCat
FROM    startdb.Item
WHERE   ItemId BETWEEN 'A' AND 'C';

-- 결과
ItemId  ItemNm           ItemCat  
------  ---------------  -------  
AMB     아메리카노(B)    COF      
AMR     아메리카노(R)    COF      
BGLR    베이글(R)        BKR      
BMFR    블루베리머핀(R)  BKR

 


​위 SQL은 다음과 같이 이상(>=) 조건과 이하(<=) 조건 두개를 사용한 것과 동일합니다.

SELECT  ItemId ,ItemNm ,ItemCat
FROM    startdb.Item
WHERE   ItemId >= 'A'
AND     ItemId <= 'C';


LIKE

LIKE는 조건값의 일부가 포함된 데이터를 검색하기 위해 사용합니다.

LIKE는 문자형 데이터에만 사용할 수 있습니다.

LIKE를 사용할때는 아래의 특수문자를 사용해 와일드카드(대체문자)로 사용합니다.

  • %: 글자 수 상관 없이 아무 문자를 의미
  • _(Under Bar): 한 글자의 아무 문자를 의미

아래는 상품명(ItemNm)이 '카페'로 시작하는 데이터를 조회하는 SQL입니다.

SELECT  ItemId ,ItemNm ,ItemCat
FROM    startdb.Item
WHERE   ItemNm LIKE '카페%';

-- 결과
ItemId  ItemNm       ItemCat  
------  -----------  -------  
CLB     카페라떼(B)  COF      
CLR     카페라떼(R)  COF

 

반대로 %를 앞쪽에 놓고 뒤에 조건 값을 사용하면, 입력한 조건 값으로 끝나는 데이터를 검색할 수 있습니다.

아래는 상품명이 '(B)'로 끝나는 데이터를 조회하는 SQL입니다.

SELECT  ItemId ,ItemNm ,ItemCat
FROM    startdb.Item
WHERE   ItemNm LIKE '%(B)';

-- 결과
ItemId  ItemNm               ItemCat  
------  -------------------  -------  
AMB     아메리카노(B)        COF      
CLB     카페라떼(B)          COF      
HCHB    핫초코(B)            BEV      
IAMB    아이스아메리카노(B)  COF      
ICLB    아이스카페라떼(B)    COF


​%를 중간에 사용하면 시작 문자, 끝 문자가 일치하는 데이터를 검색할 수 있습니다.
아래는 '아이스'로 시작하면서 끝에가 '(B)'로 끝나는 상품명을 검색하는 SQL입니다.

SELECT  ItemId ,ItemNm ,ItemCat
FROM    startdb.Item
WHERE   ItemNm LIKE '아이스%(B)';

ItemId  ItemNm               ItemCat  
------  -------------------  -------  
IAMB    아이스아메리카노(B)  COF      
ICLB    아이스카페라떼(B)    COF

 

'_'는 한 글자의 아무 문자를 의미합니다. 아래 SQL을 실행해보시기 바랍니다.

SELECT  ItemId ,ItemNm ,ItemCat
FROM    startdb.Item
WHERE   ItemNm LIKE '카페라떼(_)';

-- 결과
ItemId  ItemNm       ItemCat  
------  -----------  -------  
CLB     카페라떼(B)  COF      
CLR     카페라떼(R)  COF


​LIKE를 앞에 NOT을 붙여 부정 조건으로 사용할 수 있습니다.

아래는 ItemCat(상품종류)가 'COF'(커피) 중에서 ItemNm(상품명)에 라떼가 포함되지 "않은" 데이터를 조회하는 SQL입니다.

SELECT  ItemId ,ItemNm ,ItemCat
FROM    startdb.Item
WHERE   ItemCat = 'COF'
AND     ItemNm NOT LIKE '%라떼%';

-- 결과
ItemId  ItemNm               ItemCat  
------  -------------------  -------  
AMB     아메리카노(B)        COF      
AMR     아메리카노(R)        COF      
EINR    아인슈페너(R)        COF      
FLTR    플랫화이트(R)        COF      
IAMB    아이스아메리카노(B)  COF      
IAMR    아이스아메리카노(R)  COF      
IEINR   아이스아인슈페너(R)  COF      
IFLTR   아이스플랫화이트(R)  COF



 

​IN

IN 조건은 하나의 컬럼에 여러 값에 대한 조건 값을 비교하기 위해 사용합니다.
아래와 같이 괄호안에 필요한 조건 값을 콤마로 구분해 여러개 사용하면 됩니다.

SELECT  ItemId ,ItemNm ,ItemCat
FROM    startdb.Item
WHERE   ItemId IN ('AMB','IAMB','BGLR');

-- 결과
ItemId  ItemNm               ItemCat  
------  -------------------  -------  
AMB     아메리카노(B)        COF      
BGLR    베이글(R)            BKR      
IAMB    아이스아메리카노(B)  COF

 

위의 IN을 사용한 SQL은 아래와 같이 OR를 사용한 SQL로 변경할 수 있습니다.

SELECT  ItemId ,ItemNm ,ItemCat
FROM    startdb.Item
WHERE   (ItemId = 'AMB'
        OR ItemId = 'IAMB'
        OR ItemId = 'BGLR');


​SQL의 가독성을 위해 가능하면 OR 보다는 IN 조건을 권장합니다.
NOT LIKE와 마찬가지로 NOT IN으로 IN 조건을 부정 처리할 수 있습니다.
아래는 상품종류(ItemCat)가 'COF'(커피)이면서 Hot/Cold구분(HotColdCd)가 'HOT'인 상품 중에, ItemId(상품ID)가 'CLB'와 'CLR'이 아닌 상품만 조회하고 있습니다.

SELECT  ItemId ,ItemNm,ItemCat, HotColdCd
FROM    startdb.Item
WHERE   ItemCat = 'COF'
AND     HotColdCd = 'HOT'
AND     ItemId NOT IN ('CLB','CLR');

-- 결과
ItemId  ItemNm         ItemCat  HotColdCd  
------  -------------  -------  ---------  
AMB     아메리카노(B)  COF      HOT        
AMR     아메리카노(R)  COF      HOT        
EINR    아인슈페너(R)  COF      HOT        
FLTR    플랫화이트(R)  COF      HOT


​IN을 OR로 변경할 수 있는 것처럼 NOT IN도 NOT과 OR를 혼합한 SQL로 변경할 수 있습니다. 아래와 같습니다.

SELECT  ItemId ,ItemNm,ItemCat, HotColdCd
FROM    startdb.Item
WHERE   ItemCat = 'COF'
AND     HotColdCd = 'HOT'
AND     NOT (ItemId = 'CLB' OR ItemId = 'CLR');



WHERE 절에서 사용할 수 있는 특수 조건자로 BETWEEN, LIKE, IN을 살펴봤습니다.

제법 많이 사용하는 특수 조건자입니다.

 

지금까지 익힌 SQL 기술을 사용해 다음 BOOSTER QUIZ들을 직접 풀어보시기 바랍니다.

실습 문제를 풀어보고 싶다면 다음 글을 참고해 실습 환경을 구성하세요.

https://sweetquant.tistory.com/561

 

[StartUP SQL BOOK]실습 환경 구성하기

StartUP SQL 교육 슬라이드를 책으로 작성 중인 페이지입니다.StartUP SQL이란? 데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육입니다.현재 블로그에 전체 교육 슬라이드 무료로 오픈되어 있습니

sweetquant.tistory.com

 

 

 

 


[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

 

 

  • StartUP SQL 교육 슬라이드를 책으로 작성 중인 페이지입니다.
    • StartUP SQL이란? 데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육입니다.
    • 전체 교육 슬라이드는 무료 오픈되어 있습니다: https://sweetquant.tistory.com/497
 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

 

데이터를 시행착오 없이 잘 활용하기 위해서는 데이터 자료형에 따른 크기 비교에 대한 이해가 필요합니다.

 

 

데이터의 크기 비교

​데이터를 구성하는 가장 기본적인 데이터 자료형은 문자 또는 숫자입니다. 여기에 하나를 더 추가하면 날짜 형식의 자료형이 있습니다. 이외에도 다양한 자료형이 있지만, 기본적으로 이 세 개의 자료형이 많이 사용됩니다.

데이터를 시행착오 없이 잘 활용하기 위해서는 데이터 자료형에 따른 크기 비교에 대한 이해가 필요합니다.

 

먼저, 숫자의 크기 비교는 매우 간단합니다. 숫자의 크기 비교는 유치원생도 할줄 알죠.
1보다 2가 크고, 2보다는 10이 큽니다. 숫자 값 자체에 크기가 있기 때문에 쉽게 비교할 수 있습니다.

날짜의 크기 비교는 어떨까요?

SQL이나 프로그램을 지금까지 해왔다면, '24년 5월 2일'이 '24년 5월 1일'보다 크다라는 것을 알고 있을겁니다.

그러나 가만히 생각해 보면 날짜에 크기라는 것이 있을까요? 두 날짜 모두 24시간이라는 똑같은 시간의 양을 가진 하루입니다. 다만, 프로그램에서는 날짜의 순서를 따져 크기를 결정합니다. 보통은 순서상 앞쪽의 날짜가 작은 값, 뒤쪽의 날짜가 큰 값이 됩니다. 그러므로 '24년 5월 2일'이 '24년 5월 1일'보다 큰 값이 됩니다.

이처럼 프로그램에서는 숫자가 아닌 형태의 데이터는 일정한 기준의 순서를 적용해 크기를 결정합니다.

프로그램뿐만 아니라 데이터베이스도 마찬가지입니다.

 

문자 역시 크기가 없습니다. 그러므로 문자도 일정한 순서에 의해 크기 비교가 이루어집니다.

일반적으로 알파벳 순서나 가나다 순서에 따라 크기가 결정됩니다.
B는 A보다 크고, C는 B보다 큰 값이 됩니다. A부터 Z까지 중에는 A가 가장 작은 값, Z가 가장 큰 값이 됩니다.

여기까지 이해하는데 어려움은 없을 것입니다.

문자열의 크기 비교

문자가 두 개 이상 합쳐진 것을 문자열이라고 합니다. 'CAFE'는 C, A, F, E라는 문자 네 개가 합쳐진 하나의 문자열입니다.

문자열을 구성하는 요소가 문자이므로 문자열의 크기 비교도 문자의 규칙을 따르게 됩니다.
다만, 문자열은 문자열 전체가 아닌 각 문자열의 앞 문자부터 차례대로 크기 비교를 수행합니다. 아래의 예를 보면 쉽게 이해가 될 것입니다.

  • 'CAFE'와 'AMERICANO'의 크기를 비교
    • 문자열 전체가 아닌 첫 번째 문자부터 차례대로 크기를 비교합니다.
    • 두 문자열의 첫 번째 문자인 'C'와 'A'를 비교하면, 'C'가 'A'보다 큽니다.
    • 첫 번째 문자에서 크기가 결정되었으므로 나머지 문자들은 더이상 비교하지 않습니다.
    • 첫 번째 문자가 큰 'CAFE'가 'AMERICANO'보다 큰 값으로 처리됩니다.
  • 'CAFE'와 'COFFEE'의 크기를 비교
    • 두 문자열의 첫 번째 문자가 'C'로 서로 같습니다.
    • 첫 번째 문자가 서로 같으므로 그 다음 문자인 'CAFE'의 'A'와 'COFFEE'의 'O'를 비교합니다.
    • 'A'와 'O'를 비교하면 'O'가 큽니다. 크기가 결정되었으므로 나머지 문자는 더이상 비교하지 않습니다.
    • 첫 문자가 서로 같으므로 두 번째 문자가 큰 'COFFEE'가 'CAFE'보다 큰 값으로 처리됩니다.

이처럼 문자열의 크기 비교는 가장 앞 문자부터 차례대로 크기 비교가 이루어진다는 점을 기억하기 바랍니다.

컴퓨터 프로그램에 익숙하지 않은 사람들에게는 낯설게 느껴질 수 있는 부분입니다.

 

문자와 문자열의 크기 비교 개념을 이해했다면 다음 SQL을 실행해보시기 바랍니다.
ItemId(상품ID)에 문자열로 크기 비교 조건을 넣었고, 그에 맞는 데이터가 어떻게 나오는지 한번씩 확인해보기 바랍니다.

-- ItemId가 AMZ보다 작거나 같은 데이터 조회
SELECT  ItemId ,ItemNm ,ItemCat, HotColdCd
FROM    startdb.Item
WHERE   ItemId <= 'AMZ';

-- ItemId가 AMA보다 작거나 같은 데이터 조회
SELECT  ItemId ,ItemNm ,ItemCat, HotColdCd
FROM    startdb.Item
WHERE   ItemId <= 'AMA';

-- ItemId가 C보다 작거나 같은 데이터 조회
SELECT  ItemId ,ItemNm,ItemCat, HotColdCd
FROM    startdb.Item
WHERE   ItemId <= 'C';



​문자형 숫자

SQL의 WHERE 절에 조건 값을 줄 때 일반적으로 숫자 또는 문자 형태의 조건 값을 사용할 수 있습니다.
숫자 조건을 줄때는 숫자를 바로 입력하면 되고, 문자 형태 조건 값을 주기 위해서는 조건 값을 싱글따옴표로 처리해야 합니다. 그러면, 아래와 같은 SQL의 WHERE 절에 입력한 조건 값 '1234'는 숫자일까요? 문자일까요?

SELECT  *
FROM    TAB
WHERE   TAB_COL = '1234';


위 SQL에서 조건 값으로 사용한 '1234'는 싱글따옴표 처리가 되어 있으므로 숫자가 아닌 문자열입니다. 1234라는 값 자체는 숫자이지만, 싱글따옴표 처리를 하게 되면 이는 숫자가 아닌 문자로 인식이 됩니다. 그러므로 '1234'는 문자열의 크기 비교 규칙을 따르게 됩니다. 아래 예를 살펴보도록 하겠습니다.

  • '1234'와 '23'의 크기 비교
    • 두 값에 모두 싱글따옴표 처리했기 때문에 문자열입니다.
    • 문자열은 첫 문자부터 차례대로 비교 처리합니다.
    • '1234'와 '23'의 첫 번째 문자인 '1'과 '2'의 비교가 먼저 이루어집니다.
    • 문자 '2'가 '1'보다 크므로, '23'이 '1234'보다 큰 값으로 판정이 됩니다.

숫자 1234와 23을 비교하면 어떻게 될까요? 숫자 비교는 숫자 값 전체로 비교합니다. 그러므로 1,234(천이백삼십사)가 23(이십삼)보다 큰 값이 됩니다.

컴퓨터 속의 데이터를 자주 접해보지 않은 분들이라면 이러한 내용이 헷갈릴 수 있습니다.

"값이 온전히 숫자여도 싱글따옴표가 사용되었다면 이는 문자열이다." 이 부분을 기억하시기 바랍니다. 그리고 "문자열은 문자열의 크기 비교 규칙을 따르게 된다"는 것도 기억하시면 됩니다.

 

문자 종류에 따른 정렬 순서

문자를 아래와 같이 크게 4개로 분류해 볼 수 있습니다.

  • 특수문자: !, *, #, @와 같은 특수 기호입니다.
  • 문자형숫자: 1, 2, 3과 같은 숫자이지만 문자로 처리된 경우입니다.
  • 알파벳: 영어의 알파벳
  • 한글 또는 각 나라의 언어

위와 같은 문자 종류는 "일반적"으로 특수문자, 문자형숫자, 알파베, 한글(각 나라의 언어) 순서로 크기가 커집니다. ("일반적"을 강조한 이유는 반드시 이러한 순서가 아닐 수 있기 때문입니다.)
아래 그림과 같습니다. 같은 문자 종류 안에서는 각 종류의 규칙에 따라 크기가 결정됩니다.

또한 일부 특수문자(@나 _(Under bar))는 알파벳보다 큰 값으로 판단되기도 합니다.

 

 

이러한 문자 종류의 크기와 문자 종류별 크기는 데이터베이스나 테이블 컬럼에 설정된 CHARACTER SET과 COLLATION에 의해 결정됩니다. 다시 말해, CHARACTER SET과 COLLATION을 무엇으로 설정했는지에 따라 다른 순서로 크기가 결정될 수도 있습니다. 그럼에도 불구하고 전반적으로는 위와 같은 순서를 가지니 참고하시기 바랍니다. SQL을 배우는 과정에서는 조금 어려운 이야기 일 수 있으므로, "일반적으로 특수문자, 문자형 숫자, 알파벳, 한글 순서로 크기가 커진다" 정도만 이해하시면 될거 같습니다.

 

 

데이터 자료형에 따른 SQL

앞에서 배운 내용을 실제 SQL에 적용해 보면 이해해보도록 하겠습니다. 

아래와 같이 TestWhere라는 테이블을 생성합니다. TestWhere 테이블은 Id1과 Id2, 두 개의 컬럼으로 구성되어 있습니다.
Id1은 숫자 자료형, Id2는 문자 자료형입니다.

CREATE TABLE startdb.TestWhere
(
    Id1 INT
    ,Id2 VARCHAR(40)
);



테이블을 생성한 후에 아래와 같이 INSERT 문장을 실행합니다.
INSERT문은 테이블에 데이터를 입력하는 SQL입니다. INSERT INTO 뒤에 테이블명을 적고,
INSERT할 컬럼들을 괄호안에 적어주면 됩니다. 그리고 VALUES 부분에 앞에서 적은 컬럼 순서에 맞쳐 입력할 값을 적어주면 됩니다.

INSERT INTO startdb.TestWhere (Id1      ,Id2)
                        VALUES('1000'   ,1000);


위 INSERT 문은 에러없이 정상 실행됩니다. 그런데 좀 이상한 점이 있지 않나요?
무엇이 이상한지 테이블 생성(CREATE)문과 비교해 가면서 고민해 보기 바랍니다.

Id1은 숫자 값을 저장할 수 있는 INT 자료형입니다. 그런데 VALUES에 입력하는 값은 '1000'으로 문자 형태로 입력을 했습니다. 이 경우 DBMS가 자동으로 문자 '1000'을 테이블의 자료형인 숫자 형태로 "자동형변환"을 수행해 입력을 처리합니다.
Id2의 경우는 반대입니다. 테이블의 컬럼은 문자를 담는 VARCHAR 자료형이지만, 입력하는 값은 1000 이라는 숫자 형태로 입력을 했습니다. 마찬가지로 DBMS가 자동으로 숫자 1000을 테이블의 자료형인 문자 형태로 자동형변환을 수행해 입력을 처리합니다. 그러므로 위 SQL은 에러없이 잘 작동합니다. 이와 같은 "자동형변환"은 DBMS마다 적용 규칙이 다르거나 허용하지 않는 경우도 있습니다.

아래 SQL은 어떻게 될까요? 아래 SQL은 에러가 발생합니다.
숫자형인 Id1에 문자로 'C001'을 입력했기 때문에, 'C001'의 'C'를 숫자로 자동 변환할 수 없어 에러가 납니다.

INSERT INTO startdb.TestWhere (Id1      ,Id2)
                        VALUES('C001'   ,'C001');

 

이번에는 아래 SQL을 살펴볼까요. Id1과 Id2에 '0100'이란 문자열을 저장하고 있습니다.

INSERT INTO startdb.TestWhere (Id1      ,Id2)
                        VALUES('0100'   ,'0100');


위 SQL은 에러없이 실행됩니다. 입력한 값을 SELECT도 해보죠.

SELECT SQL의 결과를 살펴보면, Id1에 방금 입력한 값이 0100이 아니라 100인 것을 알 수 있습니다.
앞에서 설명한 것처럼 문자열 '0100'은 입력되면서 Id1의 자료형인 숫자로 자동형변환이 됩니다.
일반적인 숫자 값은 0으로 시작하는 것을 허용하지 않기 때문에, 가장 앞의 0은 제거되고 100이란 숫자만 입력이 된 것입니다.

SELECT  *
FROM    startdb.TestWhere;

Id1   Id2   
----  ----  
1000  1000  
100   0100


이처럼, 테이블에 설정한 컬럼의 자료형에 따라 입력한 값이 원래의 의도와는 다른 값이 입력될 수 있습니다. 그러므로 항상 우리가 사용하는 테이블의 자료형을 확인하는 습관을 가져야 합니다.

 

이번에는 입력된 데이터를 다양한 조건으로 조회해봅니다. 조건 값에 따라 의도하지 않은 값이 나오는 경우도 있습니다.

-- [SQL-1]
-- 숫자 자료형인 Id1에 문자 '100'을 조건으로 입력
-- 문자 조건인 '100'이 숫자로 자동형변환되어 SQL이 처리됩니다.
-- 이러한 자동형변환은 DBMS마다 다를 수 있으며, 허용하지 않을 수도 있습니다.
SELECT  *
FROM    startdb.TestWhere
WHERE   Id1 = '100';

Id1  Id2   
---  ----  
100  0100  


-- [SQL-2]
-- 문자 자료형인 Id2에 문자 '100'을 조건으로 입력
-- 문자열은 앞 문자부터 차례대로 크기 비교 처리가 됩니다.
-- 조건값 '100'과 정확히 일치하는 Id2 값이 없으므로 조회되지 않습니다.
-- Id2에는 '1000'과 '0100'만 있습니다.
-- 같다 조건을 만족하려면 문자열의 모든 값이 완전히 일치해야 합니다.
SELECT  *
FROM    startdb.TestWhere
WHERE   Id2 = '100';


-- [SQL-3]
-- 문자 자료형인 Id2에 숫자 100을 조건으로 입력
-- 이 경우 Id2의 값을 모두 숫자로 변환한 후에 숫자 조건 값 100과 비교 처리가 됩니다.
-- 그러므로 앞의 SQL과 다르게 Id2가 '0100'인 데이터가 조회됩니다.
-- '0100'의 앞의 '0'이 제거된 100이란 숫자로 자동 변환되기 때문입니다.
SELECT  *
FROM    startdb.TestWhere
WHERE   Id2 = 100;

Id1  Id2   
---  ----  
100  0100

 

이처럼 조건 값을 숫자로 사용했는지, 문자로 사용했는지, 테이블의 원래 컬럼 자료형인지 숫자인지, 문자인지에 따라 조회되는 결과가 다른 것을 알 수 있습니다.

 

실제 운영되는 시스템들의 데이터들을 보면, 컬럼에 저장된 값 자체는 숫자로만 구성되어 있지만, 실제 컬럼의 자료형을 살펴보면 문자인 경우가 있습니다. 이 경우 조건 값을 테이블의 자료형과 같은 문자로 구현하지 않으면 정확한 데이터가 조회되지 않을 수 있습니다.

SQL로 데이터를 다루기 전에, 항상 다루고자 하는 데이터를 구성한 테이블의 컬럼 자료형을 살펴보시기 바랍니다. 보다 정확히 데이터를 다룰 수 있습니다.

끝으로 다음 실습에 혼선이 없도록 만든 테이블을 DROP 하고 마무리하겠습니다.

DROP TABLE startdb.TestWhere;

 

 


SQL을 배우는 과정에 조금 지루한 이야기를 하게 된거 같습니다.

하지만 이 부분을 명확히 알고 있어야, 다양한 형태의 데이터를 혼선 없이 다룰 수 있답니다.

이상입니다.


[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

 

 

 

AND와 OR를 혼합해서 사용할 때는 반드시 괄호를 사용하자.

AND와 OR

WHERE 절에는 AND나 OR를 사용해 여러 조건을 연결해서 사용할 수 있습니다.

AND

AND는 "그리고"란 의미를 같습니다. WHERE 절에 두 조건이 AND로 연결되어 있다면, 두 조건이 모두 만족하는 레코드(로우)만 SELECT 결과에 참여하게 됩니다.

아래 SQL은 Item(상품) 테이블에서 ItemCat(상품카테고리)가 COF(커피)이면서, ItemSizeCd(상품사이즈코드)가 BIG인 상품만 조회하고 있습니다. AND를 사용해 ItemCat에 대한 조건과 ItemSizeCd에  대한 두 조건을 연결하고 있습니다.

SELECT  ItemId ,ItemNm ,ItemCat ,ItemSizeCd
FROM    startdb.Item
WHERE   ItemCat = 'COF'
AND     ItemSizeCd = 'BIG';

ItemId  ItemNm               ItemCat  ItemSizeCd  
------  -------------------  -------  ----------  
AMB     아메리카노(B)        COF      BIG         
CLB     카페라떼(B)          COF      BIG         
IAMB    아이스아메리카노(B)  COF      BIG         
ICLB    아이스카페라떼(B)    COF      BIG

 

위 SQL은 아래 그림과 같이 하나의 레코드가 두 개의 조건을 만족한 경우만 결과 집합에 포함됩니다. 하나의 조건만 만족한 데이터는 결과 집합에 포함될 수 없습니다.



아래 SQL은 조건을 세 개 사용하고 있습니다. 조건들이 AND로 연결되었으므로 세 개의 조건 모두를 만족하는 레코드(로우)만 조회 결과에 포함됩니다.

 

 

OR

OR는 "또는"이란 의미를 가지고 있습니다.

WHERE 절에 두 조건이 OR로 연결되어 있다면, 한 건의 데이터(레코드)가 두 조건 중에 하나라도 만족하면 결과에 참여할 수 있습니다.
아래 SQL을 살펴보시죠. ItemCat(상품종류)가 COF(커피)이거나 ItemSizeCd는 BIG인 상품을 조회하고 있습니다. 두 조건 중에 하나라도 만족하면 결과에 포함되는 것을 알 수 있습니다.

 

AND와 OR 동시 사용​

AND에 대해 되짚어 보면 다음과 같습니다.

  • (20>10) AND ('A'='A'): 참 AND 참이므로 결과는 참입니다.
  • (20>10) AND ('A'='B'): 참 AND 거짓이므로 결과는 거짓입니다.
  • (20>90) AND ('A'='B'): 거짓 AND 거짓이므로 결과는 거짓입니다.

이번에는 OR에 대해 되짚어보죠. 아래와 같습니다.

  • (20>10) OR ('A'='A'): 참 OR 참이므로 결과는 참입니다.
  • (20>10) OR ('A'='B'): 참 OR 거짓이므로 결과는 거짓입니다.
  • (20>90) OR ('A'='B'): 거짓 OR 거짓이므로 결과는 거짓입니다.

AND는 연결된 비교 조건이 모두 만족해야 전체가 참이되며, OR는 연결된 비교 조건중에 하나만 만족해도 전체가 참이됩니다. AND와 OR 연결자를 각각 따로 사용하는 것은 전혀 어렵지 않을겁니다.

 

하지만 두 연결자를 동시에 사용할때는 주의할 점이 있습니다. AND와 OR를 동시에 사용할 때는 반드시 괄호를 사용해 별도로 처리될 조건들을 묶어주어야 합니다. 아래는 "거짓 AND 거짓 OR 참"에 괄호를 어디에 사용했는지에 따라 결과가 달라지는 것을 보여줍니다.

  • 거짓 AND (거짓  OR  참) =  거짓  AND (참) = 거짓
  • (거짓 AND  거짓) OR  참  = (거짓) OR   참  = 참

 

동일하게 "거짓 AND 거짓 OR 참"이 사용되었지만, 괄호 위치에 따라 최종 결과가 달라지는 것을 알 수 있습니다.

그러므로 AND와 OR가 동시에 사용된다면, 반드시 괄호를 적절한 위치에 사용해야 합니다.

만약에 아래와 같이 AND와 OR가 사용되는데 괄호가 없다면, 최종 결과는! 알수가 없습니다.

  • 거짓 AND  거짓  OR  참 = ?

특정 기준에 따라 앞에서부터 순차적으로 조건 처리를 할 수도 있으며, 뒤에서부터 조건을 처리할 수도 있습니다. SQL이 복잡해질 수록 명확해지지 않으므로 AND와 OR가 동시에 사용된다면 반드시 적절하게 괄호를 사용해야 합니다.

여러분이 개발한 SQL에 AND와 OR를 동시에 사용했는데, 괄호를 빼먹었다면, 잘못 작성한 SQL일 확률이 높습니다. 또는 괄호가 없이 지금 당장 결과에 이상이 없더라도 나중에 조건이 추가되거나 변경되면서 잘못된 결과가 나올 수도 있습니다.

현업에서 아래와 같은 데이터를 요청했습니다.

  • ItemCatCD가 BEV(음료) 중에(AND) ItemSizeCd가 BIG 이거나(OR) HotColdCd가 COLD인 데이터를 조회

위 SQL은 아래와 같이 작성해야 합니다. OR 조건을 별도로 괄호로 처리해야 요구한 의미의 데이터를 정확히 추출할 수 있습니다.

SELECT  ItemId ,ItemNm ,ItemCat ,ItemSizeCd ,HotColdCd
FROM    startdb.Item
WHERE   ItemCat = 'BEV'
AND     (ItemSizeCd = 'BIG' OR HotColdCd = 'COLD');

-- 결과
ItemId  ItemNm         ItemCat  ItemSizeCd  HotColdCd  
------  -------------  -------  ----------  ---------  
CITR    유자에이드(R)  BEV      REG         COLD       
HCHB    핫초코(B)      BEV      BIG         HOT        
LEMR    레몬에이드(R)  BEV      REG         COLD       
ZAMB    자몽에이드(R)  BEV      REG         COLD

 

만약에 괄호를 사용하지 않았다면, 아래와 같이 의도하지 결과가 출력되게 됩니다.

SELECT  ItemId ,ItemNm ,ItemCat ,ItemSizeCd
FROM    startdb.Item
WHERE   ItemCat = 'BEV'
AND     ItemSizeCd = 'BIG' OR HotColdCd = 'COLD';

-- 결과
ItemId  ItemNm               ItemCat  ItemSizeCd  
------  -------------------  -------  ----------  
BMFR    블루베리머핀(R)      BKR      REG         
CITR    유자에이드(R)        BEV      REG         
CMFR    초코머핀(R)          BKR      REG         
HCHB    핫초코(B)            BEV      BIG         
IAMB    아이스아메리카노(B)  COF      BIG         
IAMR    아이스아메리카노(R)  COF      REG         
ICLB    아이스카페라떼(B)    COF      BIG         
ICLR    아이스카페라떼(R)    COF      REG         
IEINR   아이스아인슈페너(R)  COF      REG         
IFLTR   아이스플랫화이트(R)  COF      REG         
LEMR    레몬에이드(R)        BEV      REG         
ZAMB    자몽에이드(R)        BEV      REG


​AND와 OR를 동시에 사용할 때는 반드시 괄호를 사용하시기 바랍니다. 보통은 OR가 사용된 조건을 괄호로 따로 묶어야 하는 경우가 보통입니다.

 

이제 SQL을 배우고 있다면, 반드시 SQL을 직접 입력해 연습해보시기 바랍니다.

쉬운걸 연습해놓지 않는다면, 나중에 어려운 문제를 풀기는 더더욱 어려워집니다.

아래는 실습 환경을 구성하는 방법입니다.

https://sweetquant.tistory.com/561

 

[StartUP SQL BOOK]실습 환경 구성하기

StartUP SQL 교육 슬라이드를 책으로 작성 중인 페이지입니다.StartUP SQL이란? 데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육입니다.현재 블로그에 전체 교육 슬라이드 무료로 오픈되어 있습니

sweetquant.tistory.com

 


[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

  • StartUP SQL 교육 슬라이드를 책으로 작성 중인 페이지입니다.
  • StartUP SQL이란? 데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육입니다.

 

 

 

WHERE 절은 데이터 집합의 높이를 변화시키고, SELECT 절은 데이터 집합의 넓이를 변화시킵니다.


SELECT 기초 - WHERE 절 기본 사용법

SELECT SQL의 FROM 절에는 조회할 대상 테이블을 지정합니다. 그리고 테이블에서 원하는 데이터만 조회하기 위해 WHERE 절을 사용할 수 있습니다.
예를 들어, Item(상품) 테이블에서 ItemId(상품ID)가 'AMB'에 해당하는 상품만 조회하고 싶다면 아래와 같이 SQL을 작성하면 됩니다.
SELECT  ItemId ,ItemNm
FROM    startdb.Item
WHERE   ItemId = 'AMB';

-- 결과
ItemId  ItemNm         
------  -------------  
AMB     아메리카노(B)
위 SQL과 같이 WHERE 절은 FROM 절 다음에 사용합니다.
WHERE 절은 <테이블 컬럼명> <조건 연산식> <조건 값> 의 형식으로 사용합니다.
  • <테이블 컬럼명>에는 당연히 FROM 절에 사용한 테이블의 컬럼만 사용할 수 있습니다.
  • <조건 연산식>에는 <테이블의 컬럼명>과 <조건 값>을 어떤 조건으로 비교할지 정의합니다.
    • <조건 연산식>에는 아래와 같은 비교연산자를 기본적으로 사용할 수 있습니다.
    • =, !=, >, >=, <, <=
      • ItemId = 'AMB': ItemId에 저장된 값이 AMB인 경우 조회
      • ItemId != 'AMB': ItemId에 저장된 값이 AMB가 아닌 경우 조회
      • ItemId > 'Z': ItemId에 저장된 값이 'Z'보다 큰 경우 조회
      • ItemId < 'Z': ItemId에 저장된 값이 'Z'보다 작은 경우 조회
      • ItemId >= 'X': ItemId에 저장된 값이 'X'보다 크거나 같은 경우 조회
      • ItemId <= 'X': ItemId에 저장된 값이 'X'보다 작거나 같은 경우 조회
  • <조건 값>에는 <테이블 컬럼명>과 비교할 값을 입력합니다.

<조건 값>에는 일반적으로 문자 또는 숫자 형태로 조건 값을 지정할 수 있습니다. 문자로 조건 값을 줄때는 싱글따옴표(')로 조건 값을 감싸서 처리해야 합니다. 위의 예제 SQL에서 'AMB'처럼 조건을 처리한것처럼 말이죠. 조건 값을 숫자로 처리해야 한다면 싱글따옴표를 제거하면 됩니다.

 

WHERE 절을 어떻게 사용하는지 알았으니, 이제 Item(상품) 테이블에서 ItemNm(상품명)이 '아이스카페라떼(B)'인 데이터를 조회하는 SQL을 작성해보죠. 아래와 같습니다. 전혀 어렵지 않죠?

SELECT  ItemId ,ItemNm
FROM    startdb.Item
WHERE   ItemNm = '아이스카페라떼(B)';

-- 결과
ItemId  ItemNm             
------  -----------------  
ICLB    아이스카페라떼(B)
 
WHERE 절은 FROM 절의 테이블에서 조건에 맞는 데이터만 조회되도록 해줍니다.
테이블에서 필요한 데이터는 아래 그림과 같이 찾아낸다고 생각하면 됩니다. 왼쪽의 SQL을 먼저 보면 Item 테이블에서 ItemCat(상품종류)가 'BKR'(베이커리)인 데이터만 조회하고 있습니다. 이 경우, 오른쪽 그림과 같이 Item 테이블의 데이터를 한 건씩 확인해 ItemCat가 'BKR'인 레코드(로우)만 찾아서 결과로 내보내 줍니다. 아래 SQL의 경우에는 SELECT 절에서 ItemId, ItemNm, ItemCat만 사용했기 때문에, 세 개의 컬럼만 보여줍니다. 만약에 SELECT 절에 *를 사용했다면 조건에 해당하는 레코드(로우)의 모든 컬럼을 보여주게 됩니다.

 

 

위 그림은 WHERE 절 처리의 이해를 돕기 위해 테이블 전체를 순차적으로 SCAN하는 것으로 설명을 했습니다. 실제로는 테이블의 조회를 돕는 인덱스라는 객체의 존재 여부에 따라 다른 방법으로 데이터를 찾아내기도 합니다. 이러한 부분은 SQL을 완전히 익히고 나서, SQL 성능 관련한 부분을 공부해보면 아시게 됩니다.
 
 

WHERE 절에 따른 데이터 집합의 변화

WHERE 절 사용법보다 중요한걸 하나 설명드리겠습니다. 바로 우리가 사용한 SQL에 따라 데이터 집합이 어떻게 변하는지에 대해서입니다.
아래 그림을 살펴보시죠. 왼쪽과 같이 테이블에 저장된 데이터 집합은 WHERE 절을 거치면  오른쪽과 같이 데이터 집합의 높이가 낮아지게 됩니다. 
 
위 내용을 간략하게 그려보면 다음과 같습니다.
 

그리고 SELECT 절에 일부 컬럼만 적었다면, 데이터 집합은 어떻게 변할까요? 아래와 같이 넓이도 줄어들게 됩니다.

 

WHERE 절은 데이터 집합의 높이를 변화시키고, SELECT 절은 데이터 집합의 넓이를 변화시킵니다. SQL을 작성할때 이와 같이 데이터 집합이 변한다는 걸 기억해주시기 바랍니다.

아마도, 이전에 SQL을 공부해보신 분이라면 "이렇게 WHERE 절을 복잡하게 설명한다고?"라고 생각되시는 분들이 있지 않을까 싶습니다. "WHERE 절은 조건에 맞는 데이터를 테이블에서 찾아낸다."라고 간단하게 설명하고 넘어가도 될 내용을 이처럼 그림까지 그려가며 길게 설명한 이유는 SQL 문법이 아닌 제대로 데이터를 다루는 법을 알려드리고 싶기 때문입니다. 단순히 SQL 문법을 익히는게 아니라, 우리가 사용한 SQL에 따라 데이터 집합이 어떻게 변하는지 잘 알고 있어야, 나중에 조인이나 GROUP BY, 분석함수를 사용할 때 거침없이 사용할 수 있으며, 그래야만 데이터 집합을 효과적으로 자유자재로 다룰 수 있습니다.

 

오늘 준비한 내용은 여기까지입니다.

 


[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

 

 

 

요즘에 깃허브 코파일럿을 파이썬에 연동해서 사용하는중인데요...
이게... 뭐랄까..
이전에 자동 완성을 완전히 뛰어 넘네요.
예를 들어, 긴 예약어나 변수를 자동완성하는게 아니고.
그다음 코드 한줄을 완전히 자동으로 만들어 버리네요.
코파일럿이 만든 코드가 맞으면 tab만 입력하면 되네요...

기존에 GPT로 코드 도움을 많이 받으면서도 놀랐는데..
이건뭐... 대화좀 하고, 상황 설명하고, 탭만 누르면 된다니.
어허... 어허.... 어허.. 뭐라 할말이 없네요..

 

 

 

 

  • StartUP SQL 교육 슬라이드를 책으로 작성 중인 페이지입니다.
  • StartUP SQL이란? 데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육입니다.

 

MySQL 테이블 레이아웃 확인하기

 

DESC

DESC 명령어를 사용하면 테이블에 어떤 컬럼들이 있으며 어떤 자료형으로 설정되어 있는지 확인할 수 있습니다.

이미 말했듯이, 우리가 사용 할 데이터를 이해하는 것은 SQL 실력 향상에 도움이 됩니다. DESC 명령어를 통해 테이블의 컬럼과 컬럼의 자료형을 살펴보는 것도 데이터를 이해하는데 도움이 됩니다.


아래와 같이 DESC startdb.Item을 실행해봅니다.

DESC startdb.Item;


-- 결과
Field       Type          Null  Key  Default  Extra  
----------  ------------  ----  ---  -------  -----  
ItemId      varchar(40)   NO    PRI  None            
ItemNm      varchar(100)  YES        None            
ItemCat     varchar(40)   YES   MUL  None            
ItemSizeCd  varchar(40)   YES        None            
HotColdCd   varchar(40)   YES        None            
LaunchDt    date          YES        None


컬럼과 자료형을 확인할 수 있습니다. 대부분의 컬럼이 VARCHAR로 되어 있습니다. LaunchDt라는 컬럼만 DATE로 설정되어 있습니다.

 

이번에는 DESC startdb.Ord를 실행해봅니다. Ord(주문) 테이블은 주문 정보가 담겨져 있습니다. 아직 사용해본적은 없지만 앞으로 SQL을 배우면서 자주 사용하게 될 테이블입니다.

DESC startdb.Ord;

-- 결과
Field           Type             Null  Key  Default  Extra  
--------------  ---------------  ----  ---  -------  -----  
OrdNo           bigint unsigned  NO    PRI  None            
OrdDtm          datetime         YES        None            
PrepareCompDtm  datetime         YES        None            
PickupDtm       datetime         YES        None            
MemberId        varchar(40)      YES   MUL  None            
ShopId          varchar(40)      YES   MUL  None            
OrdSt           varchar(40)      YES        None            
OrdAmt          decimal(18,3)    YES        None            
PayTp           varchar(40)      YES        None

 

OrdNo는부호가 없는(UNSIGNED) 큰 정수(BIGINT)로 설정되어 있습니다.
OrdDtm(주문일시), PrepareCompDm(준비완료일시), PickupDtm(픽업일시)는 DAETIME 자료형입니다.
MySQL은 년, 월, 일만 저장할 때는 DATE 자료형을, 년, 월, 일과 함계 시분초를 저장하기 위해서는 DATETIME을 사용합니다. OrdAmt(주문금액)는 DECIMAL(18,3)으로 전체 18자리에 소수점 세 자리를 저장할 수 있도록 되어 있습니다.

DESC로 살펴본 Item과 Ord 테이블의 ERD를 표현해보면 다음과 같습니다.




여러분들이 현재 MySQL을 업무에서 사용하고 있다면, DESC로 주로 사용하는 테이블ㅇ르 한 번씩 확인해보시기 바랍니다.

INFORMATION_SCHEMA

DESC 명령어 외에도, 테이블의 구조를 확인하는 추가 방법이 있습니다.

바로 메타 테이블을 조회하는 것입니다.
메타 테이블은 데이터베이스에 만들어진 오브젝트 정보를 관리하는 별도의 시스템 테이블입니다.
대부분의 DBMS가 메타 테이블을 제공합니다. MySQL은 INFORMATION_SCHEMA라는 스키마 영역에 메타 테이블이 존재합니다.


아래 SQL로 Item의 테이블 구조를 확인할 수 있습니다.

SELECT  T1.TABLE_SCHEMA DB ,T1.TABLE_NAME Tab
        ,T1.COLUMN_NAME Col ,T1.COLUMN_COMMENT Cmt
        ,T1.ORDINAL_POSITION Pos ,T1.COLUMN_TYPE Typ
        ,T1.IS_NULLABLE Null_YN ,T1.COLUMN_KEY Ky
FROM    INFORMATION_SCHEMA.COLUMNS T1
WHERE   T1.TABLE_NAME = 'Item'
AND     T1.TABLE_SCHEMA = 'startdb'
ORDER BY pos ASC;

-- 결과
DB       Tab   Col         Cmt                 Pos  Typ           Null_YN  Ky   
-------  ----  ----------  ------------------  ---  ------------  -------  ---  
startdb  item  ItemId      상품ID              1    varchar(40)   NO       PRI  
startdb  item  ItemNm      상품명              2    varchar(100)  YES           
startdb  item  ItemCat     상품카테고리        3    varchar(40)   YES      MUL  
startdb  item  ItemSizeCd  상품사이즈코드      4    varchar(40)   YES           
startdb  item  HotColdCd   아이스/HOT구분코드  5    varchar(40)   YES           
startdb  item  LaunchDt    출시일자            6    date          YES

 

이처럼 메타 테이블을 사용하면 자신이 원하는 형태로 조회가 가능합니다.
또한, 메타테이블에는 DESC에서는 보여주지 않는 추가적인 정보들이 더 있습니다.
이 중에 SQL 작성(데이터 이해)에 많은 도움이 되는 것은 아마도 COMMENT 부분일 것입니다.
COMMENT를 통해 각 컬럼이 어떤 의미인지 확인할 수 있습니다. 물론 ERD가 있어, ERD로 확인한다면 더 좋습니다.


아래와 같이 TABLE_NAME에 대한 조건 값을 변경해 Ord 테이블의 구조도 확인해 봅니다.

SELECT  T1.TABLE_SCHEMA DB ,T1.TABLE_NAME Tab
        ,T1.COLUMN_NAME Col ,T1.COLUMN_COMMENT Cmt
        ,T1.ORDINAL_POSITION Pos ,T1.COLUMN_TYPE Typ
        ,T1.IS_NULLABLE Null_YN ,T1.COLUMN_KEY Ky
FROM    INFORMATION_SCHEMA.COLUMNS T1
WHERE   T1.TABLE_NAME = 'Ord'
AND     T1.TABLE_SCHEMA = 'startdb'
ORDER BY pos ASC;

-- 결과
DB       Tab  Col             Cmt           Pos  Typ              Null_YN  Ky   
-------  ---  --------------  ------------  ---  ---------------  -------  ---  
startdb  ord  OrdNo           주문번호      1    bigint unsigned  NO       PRI  
startdb  ord  OrdDtm          주문일시      2    datetime         YES           
startdb  ord  PrepareCompDtm  제조완료일시  3    datetime         YES           
startdb  ord  PickupDtm       픽업일시      4    datetime         YES           
startdb  ord  MemberId        회원ID        5    varchar(40)      YES      MUL  
startdb  ord  ShopId          매장ID        6    varchar(40)      YES      MUL  
startdb  ord  OrdSt           주문상태      7    varchar(40)      YES           
startdb  ord  OrdAmt          주문금액      8    decimal(18,3)    YES           
startdb  ord  PayTp           지불유형      9    varchar(40)      YES


​​

MySQL에서 테이블의 구조를 확인하는 방법을 알아봤습니다.

적을 알고 나를 알면?... 백전백승이라는 말이 있죠.

마찬가지로 데이터를 알고 SQL을 작성하면, 백전백승은 아니지만, 좀 더 효율적으로 SQL 작성할 수 있습니다.

항상, 무턱대고 SQL 문법을 외워서 사용하는게 아니라, 자신이 사용할 대상 테이블의 구조와 데이터를 먼저 이해할 수 있도록 노력해보시기 바랍니다.

 


[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com


[StartUP Tuning]

  • SQL 입문을 넘어선 MySQL을 활용한 SQL 튜닝 입문 교육
  • 2024년 5월 주말 오프라인 교육 과정을 모집중: https://cafe.naver.com/dbian/7717
 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

 

 

 

데이터 분석을 위해서는 시각화가 중요합니다.
시각화를 통해 캐치할 부분을 비교적 쉽게 찾아낼 수 있습니다.
일한 성과를 시각화하는 것도 매우 중요한 일입니다. 또한 쉽지 않은 일이기도 하고요.
그래서 데이터 시각화, 인사이트에 대한 책들을 종종 읽어보고 있습니다.



오늘은 제가 경험했던, 선만 추가했을 뿐인데 OK가 된 리포트의 사례에 대해 정리해봤습니다.

 

이전 프로젝트에서 SQL 튜닝 프로젝트 결과를 리포팅한적이 있습니다.

열심히 몇일 동안 튜닝 후 결과를 시각화해보니, 아래와 같이 결과가 나왔습니다. 아래는 SQL별 일별 평균 실행 시간을 시각화한 차트입니다.

 

차트를 보면 일별로 SQL 평균 실행시간이 들쑥날쑥합니다.

해당 시스템은, 대량의 데이터를 처리하는 복잡한 배치가 특정 요일(월과 목)에 집중 실행되어, SQL 평균 실행시간이 요일별로 들쑥날쑥한 상황입니다. 업무를 살펴보니, 월과 목요일에 주로 제품 출하가 있으며 이때마다 시스템이 버벅되는 상황이었습니다.

빨간 세로 점선을 기준으로 왼쪽은 튜닝 반영전, 오른쪽은 튜닝 반영후입니다.
전과 후를 비교해보면, 좋아지긴 좋아졌습니다.

하지만, 여전히 배치 자체가 처리해야할 물리적인 데이터 양 때문에 개선에 한계가 있으며,

개선후에도 요일별로 SQL 평균 실행 시간이 들쑥날쑥합니다.


Tip.!

이러한 대량 데이터 배치 SQL 성능의 한계를 극복하기 위해서는 개발자와 업무 담당자의 적극적인 지원이 필요하며, 상황에 따라 배치 프로세스 전체를 변경하거나 테이블 구조 변경도 고려해야 합니다. 또한 세밀한 테스트가 필요해 튜닝 작업이 쉽지 않습니다. 대부분 사이트들이 배치 작업에 대해 튜닝을 하고 싶어하지만 현실적으로 변경에 대한 작업양과 리스크가 너무 커서 실제 바꾸지 못하는 경우가 많습니다.


 

위와 같은 튜닝 결과 차트를 실무 담당 고객에게 보여주니, 결과서를 팀장에게 보고하기에는 좀 난감해보인다고 하더군요. 자세히 보고 생각해보면 좋아진건 알겠는데, 첫 눈에 성능이 개선된걸 알 수 있어야 할거 같다고 하더군요.

제가 생각해도... 위의 차트를 이용해 고객에게 프로젝트 성과를 와닿게 하기는 쉽지 않겠다는 생각이 들더군요.

 

 

그래서.. 좀 고민을 하다가... 아래와 같이 가로선을 추가해서 고객에게 보여줬습니다.

그랬더니, 고객도.. 음.. 좋아졌네요. 고개를 끄덕거리시네요.

SQL 평균실행시간- 가로선 추가

 

 

오래전 일이지만, 소개를 한번 해보면 좋겠다 싶었던 내용입니다.
데이터 분석을 위해서는 시각화가 중요합니다.

시각화를 통해 캐치할 부분을 비교적 쉽게 찾아낼 수 있습니다.

일한 성과를 시각화하는 것도 매우 중요한 일입니다. 또한 쉽지 않은 일이기도 하고요.

그래서 데이터 시각화, 인사이트에 대한 책들을 종종 읽어보고 있습니다.

 

지금 다시 보고서를 만든다면, 아래와 같이 이동평균도 이용해볼 수 있을거 같네요. 아래는 7일간의 이동평균(오렌지색 점선)을 추가한 결과입니다.

 



[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

[StartUP Tuning]

 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

 

 

  • ​StartUP SQL 교육 슬라이드를 책으로 작성 중인 페이지입니다.
  • StartUP SQL이란? 데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육입니다.

 

MySQL의 DATA TYPE

데이터 자료형(Data Type)에 대해 간단히 이해하고 넘어가도록 하겠습니다.
데이터 자료형이란 데이터가 가질 수 있는 값의 종류입니다.

데이터 자료형은 테이블을 구성하는 컬럼(속성)별로 지정이 가능합니다. 한 테이블에서 하나의 컬럼이 로우마다 다른 자료형을 가질 수는 없으며, 테이블을 생성할 때 컬럼별로 반드시 자료형을 지정해 주어야 합니다.

앞에서 살펴본 Item(상품) 테이블의 ItemNm(상품명)은 문자 형태의 데이터 자료형으로 되어 있습니다.

아직 다루진 않았지만, 뒤에서 다루게 될 Ord(주문) 테이블의 OrdAmt(주문금액)에는 숫자 데이터 자료형이 설정되어 있습니다.


​데이터 자료형은 일반적으로 DBMS(MySQL)에서 제공하는 것 중에 골라서 사용합니다.
주요 자료형에는 문자 자료형, 숫자 자료형, 날짜 자료형이 있습니다.
MySQL은 문자 값을 저장하기 위해 CHAR와 VARCHAR라는 문자 자료형을 제공합니다.
숫자 값을 저장하기 위해서는 INT(=Integer), BIGINT, DECIMAL이라는 숫자 자료형을 제공합니다.
날짜 자료형에는 DATE와 DATETIME, TIMESTAMP가 있습니다.
아래 그림과 같이 간단하게 요약해 볼 수 있습니다.

MySQL의 대표 자료형



문자, 숫자, 날짜는 다른 DBMS도 공통적으로 제공하는 데이터 자료형입니다.
다만, DBMS마다 약간씩 다른 이름으로 되어있거나 기능의 차이가 있을 수 있습니다.
문자, 숫자, 날짜 외에도 매우 많은 다양한 자료형들이 존재합니다.

MySQL에는 어떤 데이터 자료형이 있는지는 아래의 공식 레퍼런스를 참고해보시기 바랍니다.
공식 레퍼런스의 자료형을 외우실 필요는 없습니다. 필요할 때 찾아보실 수 있으면 됩니다.

위에서 살펴본 자료형에 대해 조금 더 살펴보도록 하겠습니다.

  • CHAR와 VARCHAR: 문자형 데이터를 저장합니다.
    • 괄호를 이용해 저장 가능한 문자열의 길이를 지정
    • CHAR(10): 고정 문자형 데이터 저장
      • 'ICE'와 같이 세 글자만 저장해도 내부적으로 10자리의 공간을 사용
    • VARCHAR(10): 가변 문자형 데이터 저장
      • 'ICE'와 같이 세 글자만 저장하면 그에 맞는 저장 공간만 사용
    • 공간 절약을 위해서는 일반적으로 VARCHAR를 사용합니다.
    • 일반적으로 코드성 데이터나 ID와 같이 저장될 문자 길이가 일정할 때만 CHAR를 사용하는 편입니다.
  • INT와 BIGINT: 정수를 저장하기 위해사용
    • BIGINT는 INT보다 더 큰 범위의 정수를 저장할 수 있습니다.
    • INT와 BIGINT에 UNSIGNED를 추가로 지정하면 양수만 저장이 가능합니다.
  • DECIMAL: 실수를 저장하기 위해 사용합니다.
    • 괄호안에 (10,3)과 같이 전체 자릿수와 소수점 자릿수를 지정합니다.
    • DECIMAL(10,3): 총 10자리 숫자를 저장할 수 있으며, 그 중에 세 자리는 소수점 자릿수입니다.
  • 날짜 자료형은 나중에 별도로 설명합니다.

Tip. 거거익선?

거거익선이란 말이 있습니다. TV를 살때 크면 클수록 좋다는 것을 재밌게 표현한 말입니다.

그렇다면 데이터 자료형에는 어떨까요? BIGINT는 INT보다 큰 숫자를 저장할 수 있습니다.

그러므로 앞으로 확장성을 고려하면 INT보다는 BIGINT가 더 좋을 수 있습니다. 하지만 BIGINT는 INT보다 조금 더 많은 디스크 공간을 사용합니다. 결론적으로 디스크 용량의 낭비가 발생할 수 있습니다.

VARCHAR 자료형은 어떨까요? 예를 들어 전화번호를 저장하기 위해 VARCHAR 자료형을 사용하고 허용 자릿수를 1000으로 설정할 수 있습니다. VARCHAR는 가변 자료형이기 때문에 VARCHAR(1000)으로 설정해놓고 전화번호에 해당하는 11자리만 입력해서 사용하면 공간 낭비는 없습니다. VARCHAR 특징상 어차피 11자리 공간만 할당해서 사용하기 때문입니다. 하지만 더 큰 문제가 있습니다. DB상으로 1,000자리를 허용하기 때문에 프로그램 오류나, 데이터 클린징 실수로 실제 1,000 자리의 글자가 입력될 가능성이 존재합니다. 이러한 데이터가 발생하게 되면 데이터 품질의 이슈가 발생합니다.

데이터 품질의 이슈는 데이터 활용과도 직결되는 중요한 문제입니다. 그러므로 테이블 컬럼에 자료형의 크기를 정할 때는 단순히 확장성을 고려한 거거익선이 아닌, 확장성과 실용성, 데이터 품질까지 고려한 중간 지점을 찾아야 합니다. 물론, 이 작업은 매우 어려운 일입니다. 경험치와 많은 고민이 필요하며, 고민의 결과가 답이 아닐 가능성도 있습니다. 다만, 거거익선은 아니라는 점을 기억하고 테이블의 컬럼 길이를 선정해야 합니다.


오늘 준비한 내용은 여기까지입니다.

 

 



[StartUP SQL]

데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육

교육용 슬라이드 전체 무료 오픈: https://sweetquant.tistory.com/497

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

[StartUP Tuning]

SQL 입문을 넘어선 MySQL을 활용한 SQL 튜닝 입문 교육

2024년 5월 주말 오프라인 교육 과정을 모집중: https://cafe.naver.com/dbian/7717

 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

 

 

 

MySQL의 IO 측정

SQL 튜닝을 위해 가장 눈여겨 볼 항목중 하나는 IO(Input, Output)입니다.

IO는 데이터를 디스크나 메모리에서 읽거나 쓰는 작업을 뜻합니다.

 

데이터베이스의 기본 기능은 데이터를 저장하는 것입니다.

데이터를 관리하기 위해 수 많은 데이터를 쉴새없이 저장(Input)합니다.

또한 데이터베이스에 저장된 데이터를 활용하기 위해, 수 없이 수 많은 데이터를 읽어올려(Output) 조회하게 됩니다.

이처럼 데이터베이스는 데이터를 읽고, 쓰는 작업을 주로 합니다. 이 과정에서 IO 횟수(데이터를 읽거나 저장한 횟수)에 따라 SQL의 성능이 달라집니다.

 

오라클이나 PostgreSQL은 SQL 실행시 발생한 IO 수치를 수집하거나 측정하는 것이 비교적 수월합니다.

반면에 MySQL은 이와 같은 IO 수치 측정이 번거롭게 되어 있습니다.

또한, 글로벌하게 측정이 되므로 여러 명이 동시에 사용 중인 DB에서는 측정이 불가능합니다.

아마도 스토리지 엔진과 DB 엔진이 나누어져 있는 아키텍쳐 때문인건 아닌지 생각해 봅니다.

 

어쨋든, MySQL도 IO를 측정할 수 있는 방법이 있으니 참고하시기 바랍니다.

MySQL에는 SHOW STATUS로 innodb_buffer_pool_read_requests를 확인해 IO 수치를 확인할 수 있습니다.

SQL 실행 전 후로 해당 수치를 측정해 두 수치의 차이를 구하면, 해당 SQL의 IO 수치가 됩니다.

(이미 말했듯이, 현재 DB를 혼자 사용하고 있어야 정확한 수치가 됩니다.)

 

아래는 특정 일자의 T_ORD_BIG 데이터를 조회하는 SQL의 IO를 측정하는 과정입니다.

현재 T_ORD_BIG에는 PK외에 인덱스가 없습니다. 그러므로 131,561이라는 높은 수치의 IO가 발생되고 있습니다.

실제 실행 시간도 5.9초 정도 걸립니다.

SHOW STATUS LIKE 'innodb_buffer_pool_read_requests'; -- 122952720

SELECT T1.CUS_ID ,COUNT(*) CNT
FROM   mytundb.T_ORD_BIG T1 
WHERE  T1.ORD_DT = STR_TO_DATE('20170103','%Y%m%d')
GROUP BY T1.CUS_ID;

SHOW STATUS LIKE 'innodb_buffer_pool_read_requests'; -- 123084281

SELECT 123084281 - 122952720 FROM DUAL; -- 131561

 

이제 아래와 같이 인덱스를 만들어 봅니다.

CREATE INDEX T_ORD_BIG_X01 ON mytundb.T_ORD_BIG(ORD_DT);

 

인덱스를 만들었으므로 앞에서 테스트한 SQL은 빨라질 것입니다. 빨라진다는 것은 IO 수치가 줄어든다는 것과 같습니다.

 

다시 IO수치를 측정해보면 다음과 같습니다.

IO 수치가 55889로 이전의 절반으로 줄어든 것을 알 수 있습니다. 실행시간 또한 감소되었습니다.

SHOW STATUS LIKE 'innodb_buffer_pool_read_requests'; -- 123220482

SELECT T1.CUS_ID ,COUNT(*) CNT
FROM   mytundb.T_ORD_BIG T1 
WHERE  T1.ORD_DT = STR_TO_DATE('20170103','%Y%m%d')
GROUP BY T1.CUS_ID;

SHOW STATUS LIKE 'innodb_buffer_pool_read_requests'; -- 123276371

SELECT 123276371 - 123220482 FROM DUAL; -- 55889

 

여러 명이 사용 중인 DB에서는 제대로 측정할 수 없는 단점과,

측정 방법이 불편한다는 단점이 있지만,

MySQL도 이와 같은 방법으로 IO를 측정할 수 있다는 점을 참고하시면 될거 같습니다.

 


[StartUP Tuning]

 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

 

[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

  • StartUP SQL 교육 슬라이드를 책으로 작성 중인 페이지입니다.
  • StartUP SQL이란? 데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육입니다.

 

SELECT SQL 맛보기

 

SQL을 배울 때 가장 먼저 배우고 가장 많이 사용하게 되는 것이 바로 SELECT SQL입니다.

SELECT SQL은 말 그대로 테이블에 저장된 데이터를 조회하는 SQL입니다.

SELECT SQL의 기본적인 사용법은 다음과 같습니다.

  • SELECT SQL은 일반적으로 FROM 절과 같이 사용된다.
  • FROM 절 뒤에 조회할 대상 테이블을 적는다.
    • 대상 테이블을 조회할 때 해당 테이블이 저장된 스키마(데이터베이스)를 지정할 수 있다.
    • Ex) FROM startdb.Item
  • SELECT 절에는 조회 컬럼을 적는다.
    • 조회할 컬럼이 여러 개면 콤마(,)로 구분해서 나열한다.
    • SELECT 절에 *을 사용하면 FROM 절에 정의한 테이블의 모든 컬럼을 조회한다.

앞에서 구성한 MySQL 실습환경 데이터베이스(startdb)에 접속해,

(실습환경 구성법: https://sweetquant.tistory.com/561 )

위의 사용법에 맞게 아래와 같이 SELECT SQL을 작성하고 실행해보시죠.

아래는 startdb 스키마(데이터베이스)에 존재하는 Item(상품) 테이블에서 ItemId(상품Id)와 ItemNm(상품명)을 조회한 SQL입니다.

SELECT  ItemId ,ItemNm
FROM    startdb.Item;

-- 결과
ItemId  ItemNm               
------  -------------------  
AMB     아메리카노(B)        
AMR     아메리카노(R)        
BGLR    베이글(R)            
… 생략 …

 

이번에는 Item 테이블의 모든 컬럼을 조회해보도록 하겠습니다. 아래와 같이 SELECT절에 특정 컬럼이 아닌 *을 적어주시면 됩니다.

SELECT  *
FROM    startdb.Item;

-- 결과
ItemId  ItemNm               ItemCat  ItemSizeCd  HotColdCd  
------  -------------------  -------  ----------  ---------  
AMB     아메리카노(B)        COF      BIG         HOT        
AMR     아메리카노(R)        COF      REG         HOT        
BGLR    베이글(R)            BKR      REG         HOT        
… 생략 …

 

우리는 FROM 절에 Item이란 테이블을 지정했습니다. Item은 아래와 같이 설계된 테이블입니다. Item 테이블에는 상품ID, 상품명, 상품카테고리, 사이즈코드, Hot/Cold구분, 출시일자와 같은 정보가 담겨져 있습니다. 현재 우리가 실습하는 커피 프랜차이즈 데이터베이스에서 판매하는 상품의 마스터 정보를 관리하는 테이블입니다.

 

지금까지 SQL 교육을 진행해보니 데이터 자체를 이해하고 있는 사람(업무적으로 해당 데이터와 관련이 있는 사람)이 좀 더 빠르고 정확하게 SQL을 익히는 것을 경험했습니다. 그러므로 단순히 SQL 문법을 익히는 것이 아니라 SQL을 사용해 어떤 데이터를 어떻게 다루는지 이해하는 것도 SQL 실력 향상에 매우 중요하다 할 수 있습니다.

StartUP SQL 교육 슬라이드의 거의 모든 곳에 테이블 설계 구조를 같이 붙여 놓은 이유입니다. (저는 얼마나 번거로웠는지 모릅니다.) 단순히 SQL 문법을 보고 타이핑하고 실행만하는 것이 아니라, 우리가 사용한 데이터가 어떤 정보를 담고 있는지 이해하기 위해 노력해보기 바랍니다. 좀 더 빠르게 SQL 실력을 끌어 올릴 수 있습니다.

 

앞에서는 두 줄로 나누어서 SELECT SQL을 작성했습니다. SQL 세계에서 SQL 하나의 문장은 세미콜론(;)으로 구분됩니다. 세미콜론으로 SQL이 구분되므로 아래와 같이 하나의 SQL을 여러 줄에 나누어서 사용해도 상관없습니다. 세미콜론으로 SQL만 정확히 구분해주시면 됩니다. 아래는 모두 같은 SQL입니다.

 

간단한 SELECT 맛보기였습니다.

오늘도 즐거운 하루 되시기를!

 


[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

[StartUP Tuning]

  • SQL 입문을 넘어선 MySQL을 활용한 SQL 튜닝 입문 교육
  • 2024년 5월 주말 오프라인 교육 과정 모집중: https://cafe.naver.com/dbian/7717
 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

 

 

 

 

 

  • StartUP SQL 교육 슬라이드를 책으로 작성 중인 페이지입니다.
  • StartUP SQL이란? 데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육입니다.

 

실습 환경 구성하기

StartUP SQL은 이론으로만 SQL을 설명하지 않습니다. 풍부한 예제를 직접 실습해볼 수 있는 환경과 직접 풀어볼 수 있는 문제를 수록하고 있습니다.

SQL 실력 향상을 위해서는, SQL을 직접 실행해보고 그에 따라 테이블의 데이터가 어떻게 데이터가 조회되는지 살펴볼 필요가 있습니다. 그리고 배운 것을 자신의 것으로 완전히 만들기 위해 그에 따른 응용 문제도 풀어볼 필요가 있습니다. 이러한 연습을 위해서는 자신의 개인 PC에 실습 환경을 구성해야 합니다.

StartUP SQL은 MySQL을 활용해 SQL을 연습합니다. MySQL은 무료 DB로서 최근에 많은 스타트업 기업들이 애용하는 DBMS입니다. 설치도 쉬우며, 사용하기도 비교적 편합니다.

 

실습 환경 구성은 다음과 같은 과정을 거칩니다.

1. 완성된 실습환경

2. MySQL 다운로드

3. MySQL 설치(Workbench라는 SQL 툴이 같이 설치됨)

4. Workbench 실행

5. Workbench 설정 변경(연습과 실습을 위해 몇 가지 설정을 바꿔 놓는 것이 좋습니다.)

6. DBeaver 설치 및 실행

7. DBeaver 설정 변경

8. 데이터베이스 IMPORT

 

 

먼저 완성된 실습 환경은 아래 그림과 같습니다.

StartUP SQL 실습 환경

 

개인 PC에 MySQL 8(윈도우즈, 맥 모두 가능)을 설치하고 startdb라는 데이터베이스를 구성합니다.

startdb는 제가 직접 만들어 공유 드리는 다양한 테이블과 데이터를 담고 있는 실습용 데이터베이스입니다. 개인적으로 이런 실습용 데이터베이스를 무료로 공개하는 것은 아쉽지만, 많은 분들이 좀 더 데이터와 SQL을 잘 배울 수 있었으면 하는 바램으로 무료로 공개하게 되었습니다.

 

MySQL 다운로드 및 설치

MySQL을 다운로드하고 설치하는 과정은 아래 글을 보시고 차분히 따라해보십시오. 생각보다 어렵지 않게 해내실 수 있을 겁니다.

https://sweetquant.tistory.com/501

 

2-1~2-3. MySQL 설치

실습환경을 준비하기 위해 MySQL을 설치합니다.실습을 하지 않는다면, SQL 실력은 전혀 늘지 않습니다.        이전 교육 슬라이드: https://sweetquant.tistory.com/500 다음 교육 슬라이드: https://swee

sweetquant.tistory.com

 

 

Workbench로 MySQL 접속해보기

MySQL을 설치한 후에는 MySQL을 설치할때 같이 설치된 Workbench라는 SQL 툴을 실행해봅니다.

Workbench라는 툴을 통해 MySQL의 데이터베이스에 접속해서 SQL을 실행할 수 있습니다. 이와 함께 Workbench의 몇 가지 옵션을 변경합니다. 그리고 DBeaver라는 툴도 추가로 설치합니다. 사실 DBeaver는 설치 안해도 상관없습니다. 하지만 최근의 많은 스타트업 기업들이 SQL 무료 툴로 DBeaver를 사용하고 있으므로 사용해보시길 권장합니다. 사실, SQL 툴은 MySQL만 지원한다면 아무거나 사용해도 상관없습니다. 다만, 이후 실습 데이터베이스 구성을 위해 DATA IMPORT 작업을 해야 하는데 이때는 Workbench를 꼭 사용해야 합니다. 지금까시 설명한 과정은 아래 글을 참고해주시면 됩니다.

https://sweetquant.tistory.com/502

 

2-4~2-5. MySQL접속해보기:Workbench와 DBeaver

데이터를 강력하게 다루는 SQL.SQL을 배우기 위한 최적의 시작점, StartUP SQL! 설치한 MySQL에 접속하기 위한 SQL 툴에 대한 설명입니다.MySQL을 설치하면 Workbench는 자동설치됩니다.Workbench만 사용해도 S

sweetquant.tistory.com

 

 

실습 데이터베이스 구성하기

마지막으로 실습용 데이터베이스를 IMPORT 할 차례입니다. 첨부로 올려드린 DUMP 파일을 다운로드 한 후에, Workbench에 접속해 DATA IMPORT 작업을 수행합니다. 과정이 복잡하지 않지만, 좀 더 이해가 쉽게 하도록 영상으로 과정을 만들어 올려드렸습니다. DUMP 파일 다운과 데이터베이스 IMPORT 과정은 아래 글을 참고해주세요.

https://sweetquant.tistory.com/503

 

2-8. 실습 데이터베이스 구성하기

실습을 위한 데이터베이스를 구성할 차례입니다.해당 과정을 진행하기 전에 MySQL 8이 설치되어 있어야 합니다. (MySQL 8.0.35 추천)아래 파일을 압축을 푼후 MySQL Workbench에서 IMPORT 작업을 해주시면

sweetquant.tistory.com

 

여기까지 완료하시면, 자신의 컴퓨터에 SQL 교육과 실습을 위한 startdb라는 멋진 데이터베이스가 만들어집니다.

이제 본격적으로 SQL을 연습을 하러 가시면 됩니다.

책 형태로 SQL을 설명드리기에는 많은 시간이 걸리므로, 우선은 교육 슬라이드를 보고 하나씩 따라해보시기 바랍니다.

 

자신이 SQL이란걸 해본적이 전혀 없다면, SELECT SQL부터: https://sweetquant.tistory.com/504

그래도 SELECT SQL은 좀 배웠다면 GROUP BY 부터: https://sweetquant.tistory.com/514

GROUP BY까지 배웠다면 JOIN 부터: https://sweetquant.tistory.com/521

JOIN까지 다 배웠다면, 분석함수만 살펴보시죠!: https://sweetquant.tistory.com/545

 

오늘 준비한 내용은 여기까지입니다. 시간 나는대로 다음 내용도 준비해보도록 하겠습니다.

감사합니다.

 


[StartUP Tuning]

SQL 입문을 넘어선 MySQL을 활용한 SQL 튜닝 입문 교육

2024년 5월 주말 오프라인 교육 과정을 모집중: https://cafe.naver.com/dbian/7717

 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

 

 

 

2024년 5월 StartUP Tuning 교육의 교재 상세 목차입니다.

StartUPTuning_교재상세목차_202405.pdf
0.25MB

 

 

아래 파일은 실습에 사용할 스크립트입니다. 수강생분들께만 공유되는 자료로 압축에 암호가 설정되어 있습니다.

  - 실습 DB 구성 스크립트와 실습 스크립트, BOOSTER QUIZ 스크립트가 담겨져 있습니다.

(교육 참석 인원분들께만 현장에서 암호를 공유드릴 예정입니다.)

StartUPTuning_수강생공유자료_20240512.zip
0.21MB

 

 

감사합니다.



[StartUP Tuning]

 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

 

[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

'SQL > StartUP Tuning' 카테고리의 다른 글

MySQL의 IO 측정  (0) 2024.05.07
최근 주문 목록 SQL 성능 개선하기  (3) 2024.05.03
INDEX 개념 잡기  (0) 2024.04.30
MySQL EXPLAIN ANALYZE #2  (0) 2024.04.29
StartUP Tuning For MySQL 24년 5월 오프라인 교육 목차  (0) 2024.04.26
MySQL EXPLAIN ANALYZE  (0) 2024.04.25
StartUP Tuning Booster Quiz Sample  (0) 2024.04.23
언제까지 인덱스를 탈 것인가?  (0) 2024.04.17

 

StartUP Tuning(MySQL): 최근 주문 목록 SQL 성능 개선하기

 
DBMS: MySQL 8.0.35
 
스타벅스 앱을 키면 Quick Order에는 최근 주문 내역을 보여줍니다.
사용자에게 앱을 키자마자 최근주문 내역을 보여줘 조금 더 편리하게 앱을 사용할 수 있도록 한 것입니다.
다른 많은 시스템이나 플랫폼도 비슷합니다. 접속을 하면, 마지막 접속기록이나 최근 구매 내역을 보여줍니다.
이와 같은 기능을 처리하는 SQL의 성능 개선 과정을 간단히 살펴보겠습니다.
 
실습을 위해 Ord(주문), OrdDet(주문상세), 상품(Item) 테이블을 사용합니다.
해당 테이블은 StartUP SQL의 무료 스크립트를 통해 자신의 환경에도 생성할 수 있습니다.
참고: https://sweetquant.tistory.com/503

 

2-8~2-10. 데이터베이스 구성하기

실습을 위한 데이터베이스를 구성할 차례입니다. 포스트 가장 아래 첨부 파일로 올린 스크립트를 사용해 실습을 위한 데이터베이스를 구성합니다. 개인적으로 피같은 스크립트이지만, 모두가 S

sweetquant.tistory.com

 
Ord와 OrdDet, Item 테이블의 ERD를 살펴보면 다음과 같습니다.

 
위 테이블들을 이용해 특정 회원의 최근 주문 상품 세 개를 가져오려고 합니다. 아래와 같이 SQL을 구현할 수 있습니다.

SELECT  T2.ItemId
        ,T3.ItemNm
        ,T1.OrdDtm
        ,T1.OrdNo
FROM    startdb.Ord T1
        INNER JOIN startdb.OrdDet T2 ON (T2.OrdNo = T1.OrdNo)
        INNER JOIN startdb.Item T3 ON (T3.ItemId = T2.ItemId)
WHERE   T1.MemberId = 'M0001'
ORDER BY T1.OrdDtm DESC
LIMIT 3;

 - Time sec: 0.018636
   * Rows read: 1263
   * Buffer pages: 3797

 
SQL의 마지막에 수행 시간과 IO(Buffer pages) 수치를 첨부했습니다. 0.018초로 그렇게 느리다고 할 수는 없는 SQL입니다. 하지만 데이터 3건만 보여주는 상황에서 3,797이란 IO 수치는 약간 높은 편입니다. 수십만 명의 회원이 동시에 사용한다고 생각해보면, 약간씩 더 느려질 소지가 있습니다.
위 SQL이 현재 시스템에서 매우 많이 사용되는 핵심 SQL이라면 당연히 추가 성능 개선이 필요합니다. SQL의 성능 개선을 위해 가장 먼저 할일은 실행계획을 확인하는 것입니다. 위 SQL의 실제 실행계획은 아래와 같습니다.

1. -> Limit: 3 row(s)  (actual time=162..162 rows=3 loops=1)
2.     -> Nested loop inner join  (actual time=162..162 rows=3 loops=1)
3.         -> Nested loop inner join (actual time=162..162 rows=3 loops=1)
4.             -> Sort: startdb.t1.OrdDtm DESC   (actual time=162..162 rows=3 loops=1)
5.                 -> Index lookup on T1 using Ord_FK01 (MemberId='M0001')  (actual time=18.5..161 rows=1257 loops=1)
6.             -> Filter: (startdb.t2.ItemId is not null)  (actual time=0.027..0.0288 rows=1 loops=3)
7.                 -> Index lookup on T2 using PRIMARY (OrdNo=startdb.t1.OrdNo)  (actual time=0.0261..0.0277 rows=1 loops=3)
7.         -> Single-row index lookup on T3 using PRIMARY (ItemId=startdb.t2.ItemId)  (actual time=0.0104..0.0105 rows=1 loops=3)

 
실행계획을 확인해 보면 세 테이블이 모두 NL(Nested Loop) 방식으로 조인되고 있습니다. 성능 개선을 위해서는 이러한 조인 방식을 이해하는 것이 매우 중요합니다. 이 부분을 여기서 다루자면 길어지므로 나중에 기회가 되면 별도로 이야기하도록 하겠습니다.
실행계획이 익숙하지 않은 분들은, 실행계획에서 문제가 되는 부분을 찾기가 쉽지 않을 것입니다.
실행계획의 마지막 단계(1번 라인)의 actual time을 보면 162..162(시작시간ms..종료시간ms)입니다. 162ms에 이 SQL이 완료되었다는 것을 알 수 있습니다.
이제, 마지막 단계를 제외하고 각 단계별로 actual time을 살펴봅니다. 가장 많은 시간을 차지하는 단계를 한 번 찾아보는거죠. 5번 단계가 다른 단계들에 비해 많은 시간을 사용하고 있는 것을 알 수 있습니다. 5번 단계의 작업 내용은 아래와 같습니다.
-> Index lookup on T1 using Ord_FK01 (MemberId='M0001')  (actual time=18.5..161 rows=1257 loops=1)
 
T1(Ord) 테이블을 Ord_FK01 인덱스를 사용해 Lookup 처리하고 있습니다. Ord_FK01은 MemberId로 구성된 인덱스입니다. 실행계획에서 actual 항목의 rows를 보면 1257입니다. Ord_FK01을 이용해 추출한 데이터가 1257건이라는 뜻입니다.
우리가 필요한건 최근 조회 세 건인데, 1257건의 주문 데이터에 접근한 것입니다. 바로 이 부분에 비효율이 있다라고 할 수 있습니다.
 
우리는 성능을 개선하기 위해 아래와 같은 인덱스를 만들어 볼 수 있습니다.
CREATE INDEX Ord_X01 ON startdb.Ord(MemberId, OrdDtm);
 
인덱스를 만든 후에 다시 같은 SQL을 실행해보고 실제 실행계획을 추출해보면 아래와 같습니다.

1. -> Limit: 3 row(s)  (actual time=0.227..0.271 rows=3 loops=1)
2.    -> Nested loop inner join   (actual time=0.226..0.269 rows=3 loops=1)
3.        -> Nested loop inner join  (actual time=0.208..0.242 rows=3 loops=1)
4.            -> Covering index lookup on T1 using Ord_X01 (MemberId='M0001') (reverse)  (actual time=0.178..0.182 rows=3 loops=1)
5.            -> Filter: (startdb.t2.ItemId is not null)  (actual time=0.0155..0.0186 rows=1 loops=3)
6.                -> Index lookup on T2 using PRIMARY (OrdNo=startdb.t1.OrdNo)  (actual time=0.0149..0.0178 rows=1 loops=3)
7.        -> Single-row index lookup on T3 using PRIMARY (ItemId=startdb.t2.ItemId)  (actual time=0.00827..0.00837 rows=1 loops=3)
        
 - Time sec: 0.005036
   * Rows read: 9
   * Buffer pages: 17
   * Disk reads: 0

 
총 실행시간이 0.005초로 인덱스를 만들기 전인 0.018초에 비해 1/3 이상으로 감소했습니다. IO 수치인 Buffer pages도 3,797에서 17로 획기적으로 감소한 것을 알 수 있습니다.
실행계획의 4번 단계를 살펴보면 다음과 같습니다.
-> Covering index lookup on T1 using Ord_X01 (MemberId='M0001') (reverse)  (actual time=0.178..0.182 rows=3 loops=1)
 
새로 만든 인덱스를 Covering Index lookp으로 처리하고 있습니다. 또한 (reverse)라고 표시되어 있는데, 이는 인덱스 리프 데이터를 역순으로 접근하는 방식을 뜻합니다. 인덱스의 리프 데이터는 인덱스 키 값으로 정렬되어 있으므로 이처럼 역순으로 접근해 세 건만 읽어들이면, 최근 주문 세건을 추출해낼 수 있습니다. 4번 단계의 rows를 보면 3으로 줄어든 것을 알 수 있습니다.
 
최근 데이터 조회에 적절한 인덱스를 만들때는 WHERE 절의 조건을 인덱스의 앞쪽 컬럼으로 배치하고 ORDER BY에 있는 컬럼을 인덱스의 뒤쪽 컬럼에 배치합니다. 그러므로 위 SQL에서 WHERE 조건인 MemberId, ORDER BY 컬럼인 OrdDtm을 조합해 Ord_X01(MemberId, OrdDtm)으로 인덱스를 구성한 것입니다. (SQL에 따라 이와 같은 인덱스 구성이 불가능하고나 복잡한 경우도 많습니다.)
 
이처럼 인덱스를 만들어주는 것만으로 최근 주문을 조회하는 SQL 성능이 획기적으로 개선되었습니다.
그런데 중요한건, "인덱스를 만들자"가 아닙니다. 실행계획을 먼저 살펴보고, 성능에 문제가 되는 지점을 찾아내는 것입니다. 그리고 그에 맞게 개선안을 적용해야 합니다. 또한 지금 살펴본 SQL보다 훨씬 복잡해서 단순 인덱스 전략으로 성능 개선을 만들어 내지 못하는 경우도 많습니다.
그러므로 우리는 성능 개선을 위해 단순히 인덱스를 만들자가 아닌, 조인의 작동원리, 인덱스의 구조와 작동원리를 잘 알고 있어야 합니다.
 
오늘 준비한 내용은 여기까지입니다. 감사합니다.


 
[StartUP Tuning]

 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

 
[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

 

지난 글에서 DBeaver에 GPT를 연동하는 방법을 살펴봤습니다.

https://sweetquant.tistory.com/557

 

DBeaver에 GPT 연동하기

파이참에 Copilot을 연결해서 사용하다... 음.. SQL툴에도 AI 연동이 가능할거 같은데란 생각이 들어서.찾아보니.. DBeaver에 GPT API를 연동할 수가 있네요. 준비물DBeaver(저는 24.0.3 버젼을 사용했습니다

sweetquant.tistory.com

 

간단한 SQL은 잘 작성합니다. 조금(?) 복잡한 SQL을 GPT로 시도해봤습니다.

우선, DBeaver에 연동해서 API 형태로 GPT를 사용하는 것은 실제 OpenAI에 접속해 GPT와 채팅하면서 답변을 얻는 것과는 차이가 있어 보입니다. 아무래도 GPT와 채팅하면서 얻는 답변이 좀 더 품질이 좋아보입니다.

 

테스트한 결과를 살펴보겠습니다.

먼저, 매장 테이블과 주문 테이블을 조인하는 간단한 SQL을 요청했습니다.

SQL에 성능 문제가 발생되도록 작성되었습니다. OrdDtm 컬럼을 DATE_FORMAT으로 가공해  인덱스가 있어도 사용을 못하도록 SQL이 만들어졌습니다. 그리고 아래 SQL의 프롬프트는 제 실수가 있었습니다. 사실 매장등급이란 컬럼은 없습니다. 없으면 없다고 메시지를 주면 좋은데, 그러지는 않네요. 자신이 생각할때 적절하다고 생각한 컬럼을 사용해 결과를 만들어 냅니다.

 

-- 프롬프트: 매장 테이블과 주문 테이블을 조인해서 보여줘,
-- 주문일시가 2022년 12월이고, 매장등급이 플래티넘(PLAT)인 데이터만 조회해줘
SELECT *
FROM shop s
JOIN ord o ON s.ShopId = o.ShopId
WHERE DATE_FORMAT(o.OrdDtm, '%Y%m') = '202212' AND s.ShopSt = 'PLAT';

 

이번에는 성능을 고려하라고 프롬프트를 추가하고, 매장이 아닌 회원과 조인을 요청합니다. 이번 SQL은 100점입니다. 인덱스 사용을 고려해달라고 요청하니 OrdDtm에 적절하게 조건 처리를 했습니다. 물론, OrdDtm에 인덱스는 아직 없지만요.

-- 프롬프트
-- 회원 테이블과 주문 테이블을 조인해서 보여줘, 
-- 주문일시가 2022년 12월이고, 회원등급이 플래티넘(PLAT)인 데이터만 조회해줘. 
-- 성능을 고려해서 SQL을 작성해줘. 인덱스를 사용할 수 있게 SQL을 작성해야 한다는 거지.
--  Sure, here is the SQL query that joins the `member` and `ord` tables, and filters for orders made in December 2022 by members with a 'PLAT' grade. This query is optimized for performance by using the appropriate indexes.
/*
This query joins the member and ord tables on the MemberId field.
It then filters for orders made in December 2022 and by members with a 'PLAT' grade.
The WHERE clause is written in a way that allows the use of indexes for performance optimization.
*/
SELECT m.*, o.*
FROM `member` AS m
INNER JOIN ord AS o ON m.MemberId = o.MemberId
WHERE m.MemberGd = 'PLAT'
AND o.OrdDtm >= '2022-12-01 00:00:00'
AND o.OrdDtm < '2023-01-01 00:00:00';
--  Please note that the date format and the 'PLAT' value are just examples and should be replaced with the actual format and value used in your database. Also, make sure that there are indexes on the `MemberId`, `MemberGd`, and `OrdDtm` fields for optimal performance.

 

 

 

조금 수준을 올려봅니다. StartUP SQL에서 사용하는 퀴즈를 활용해봅니다. https://sweetquant.tistory.com/542 의 마지막에 있는 16-4번 문제입니다. 그러나 여전히 성능 관점에서는 빵점 SQL이네요.

문제:
--  [BOOSTER QUIZ 16-4] 가입년도별, 회원상태별 2023년 1월의 주문 건수를 구하시오.
--  특정 가입년도별, 회원상태별 주문이 없어도 0건으로 집계해서 출력해주세요. 그리고 가입년도별 주문건수와 전체 주문건수도 추가해서 보여주세요.
--   - 대상 테이블: 회원(Member), 주문(Ord)
--   - 조회 조건: OrdDtm이 2023년 1월인 주문 데이터
--   - 조회 컬럼: JoinYear, MemberSt, OrdCnt
--   - 추가 조건:
--      : 성능을 고민하고 인덱스를 사용할 수 있도록 SQL을 작성할것.
--      : JoinYear는 JoinDtm을 년도로 변환한 값
--      : JoinYear별, MemberSt별 GROUP BY 처리하시오.
--      : OrdCnt는 JoinYear, MemberSt별 주문 건수
--      : Member와 Ord를 아우터 조인해 주문이 없는 JoinYear, MemberSt도 주문 건수가 0건으로 출력되도록 하시오.
--      : ROLLUP을 사용해 JoinYear별 중간합계와 전체합계를 추가하시오.
    
DBeaver+GPT 답변:

SELECT 
    YEAR(m.JoinDtm) AS JoinYear,
    m.MemberSt,
    COUNT(o.OrdNo) AS OrdCnt
FROM 
    `member` m
LEFT JOIN 
    ord o ON m.MemberId = o.MemberId AND YEAR(o.OrdDtm) = 2023 AND MONTH(o.OrdDtm) = 1
GROUP BY 
    YEAR(m.JoinDtm), m.MemberSt WITH ROLLUP;

 

 

조금 더 수준을 올려봅니다. 세개 테이블 조인과 분석함수까지 사용해야 하는 SQL입니다.

(문제 출처: https://sweetquant.tistory.com/548 )

휴~ 다행이네요. 아래 SQL은 에러가 발생합니다. SELECT 절에서 ItemId 컬럼을 사용할때 테이블이 지정되지 않았기 때문이죠.

--  [BOOSTER QUIZ 20-2] 2022년 11월 2022년 12월 주문에 대해, 주문년월별 상품별 주문수량을 구해주세요, 주문년월별로 주문수량에 따른 순위를 구해주세요.
--   - 대상 테이블: 주문(Ord), 주문상세(OrdDet), 상품(Item)
--   - 조회 조건: OrdDtm이 2022년 11월부터 2022년 12월 말까지인 데이터
--   - 조회 컬럼: OrdYm, ItemId, ItemNm, SumOrdQty, RankOverByYm
--   - 추가 조건:
--      : OrdYm, ItemId별 GROUP BY 처리하시오.
--      : OrdYm은 OrdDtm을 DATE_FORMAT으로 년월 형태로 변환한 값입니다.
--      : SumOrdQty는 OrdYm, ItemId별 SUM한 OrdQty 값입니다.
--      : RankOverByYm은 ItemId의 판매수량(SumOrdQty)에 대한 순위입니다. 이 순위는 년월별로 구해야 하며 판매 수량이 높으면 1이 됩니다.

SELECT 
    DATE_FORMAT(OrdDtm, '%Y%m') AS OrdYm,
    ItemId,
    ItemNm,
    SUM(OrdQty) AS SumOrdQty,
    RANK() OVER (PARTITION BY DATE_FORMAT(OrdDtm, '%Y%m') ORDER BY SUM(OrdQty) DESC) AS RankOverByYm
FROM 
    ord 
JOIN 
    orddet ON ord.OrdNo = orddet.OrdNo
JOIN 
    item ON orddet.ItemId = item.ItemId
WHERE 
    OrdDtm BETWEEN '2022-11-01' AND '2022-12-31'
GROUP BY 
    DATE_FORMAT(OrdDtm, '%Y%m'), 
    ItemId, 
    ItemNm
ORDER BY 
    OrdYm, 
    RankOverByYm;--  This query will return the total quantity of each item ordered per month for November and December 2022, along with a rank for each item based on the quantity ordered. The rank is calculated separately for each month.

 

 

DBeaver에 GPT API를 연동해 다양한 SQL을 시도해봤습니다.
아직은 API 연동으로 복잡한 SQL을 작성하는 데는 한계가 있어 보입니다.

(GPT와 직접 채팅으로 시도해보면 좀 더 결과가 잘나오지 않을까 싶네요.)
그러나 책으로만 SQL을 배운 신입보다는 낫다고도 할 수 있습니다.

지금은 AI를 활용한 SQL 작성에 한계는 있어보이지만,
개인적으로는 언젠가 이 한계를 극복할 것이라고 생각합니다.

다만, GPT가 잘할거라고 해서 우리가 공부를 게을리 해도 된다는 것은 아닙니다.
오히려 이전보다 더 깊이있게 공부할 필요가 있다고 생각합니다.
우리가 잘 알아야 잘 시킬 수 있으니까요..
언젠가는 시킬 일 조차 없게 될지도 모르지만, 그때는 그때고요.
오늘은 노력해야 하지 않을까요?

 

바짝 긴장해라. H.U.M.A.N!

 


[StartUP Tuning]
SQL 입문을 넘어선 MySQL을 활용한 SQL 튜닝 입문 교육
2024년 5월 주말 오프라인 교육 과정 모집중: https://cafe.naver.com/dbian/7717

 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

 

[StartUP SQL]
데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육
교육용 슬라이드 전체 무료 오픈: https://sweetquant.tistory.com/497

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

파이참에 Copilot을 연결해서 사용하다... 음.. SQL툴에도 AI 연동이 가능할거 같은데란 생각이 들어서.

찾아보니.. DBeaver에 GPT API를 연동할 수가 있네요.

 

준비물

DBeaver(저는 24.0.3 버젼을 사용했습니다. 아주 오래된 버젼 아니면 문제 없을거 같습니다.)

GPT 계정과 별도의 GPT API 결제 필요.(유료입니다.)

 

1. DBeaver를 실행하고 상단 메뉴 도움말(H)에서 Install New Software... 를 선택합니다.

 

2. Work with 부분에 AI를 검색해 DBeaver AI Intergration을 선택합니다.

   - 그 후 아래 목록에서 DBeaver AI Support 를 체크한 후에 다음(N) 버튼을 클릭합니다.

   - Install Details 에서도 다음으로 그냥 넘어갑니다.

 

3. 동의 및 완료를 클릭

   - 그다음 권한 관련해서는 모두 체크후 Trust 버튼 클릭

   - 권한 관련 체크가 두번 나오는데, 왠지 불안하지만 체크를 안하면 작동안할거 같아서 일단 체크하고 넘어감

   - 회사 DB에 접근하는 상황이라면 왠만하면 내용을 꼼꼼히 읽어보고 체크할 것을 권장합니다.

   - Restart로 DBeaver를 재시작합니다.

 

 

4. DBeaver가 Restart되는 동아 Openai에 가서 API키를 발급합니다.

   - API Key 같은 경우 생성할때만 확인해서 카피해놓을 수 있으며, 나중에 재확인이 불가합니다.

   - API Key 사용에 대해 미리 별도 결제가 필요합니다.

     (개인 용도로 잠깐씩 쓰는 것은 생각만큼 많이는 안나오는거 같네요. 키 발급후 키가 공개되지 않도록 주의 필요)

   - https://platform.openai.com/api-keys 접속

   - 왼쪽 api keys 선택 > 가운데  Create new secret key 클릭해서 키를 새로 생성

   - 여기서 만든 Key를 DBeaver의 AI 창에 입력해줘야 합니다. 

 

 

 

5. DBeaver를 재시작하면, SQL창 왼쪽에 GPT 마크의 버튼이 나타납니다. 해당 버튼을 클릭합니다.

   - AI 설정창이 뜨면, Service를 선택하고 API Token에 조금전에 받은 API 키를 입력후 Apply and Close를 선택합니다.

   - 현재 선택한 DB의 테이블과 컬럼에 대한 메타데이터를 AI업체에 넘겨도 되냐고 질문합니다.

   - 그래야 AI가 SQL을 작성할 수 있으니, Yes를 선택합니다.

     : 회사 DB에서 이와 같이 하시면, 아마도 안되겠죠!

 

6. 모든 준비는 끝났습니다. 이제 다시 SQL 창 왼쪽에 GPT 마크 버튼을 클릭하고, 텍스트로 SQL을 요청하면 됩니다.

 

간단한 SQL은 잘 만들어주네요.^^ 점점점 발전하겠죠. AI 무섭슴다...

 

 

준비한 내용은 여기까지입니다. 다음 글에서는 조금 더 복잡한 SQL을 시켜볼까 합니다.

테스트해본바로는, "여전히 SQL 공부는 해야 한다!"가 개인적인 결론입니다.

 


[StartUP Tuning]

  • SQL 입문을 넘어선 MySQL을 활용한 SQL 튜닝 입문 교육
  • 2024년 5월 주말 오프라인 교육 과정 모집중: https://cafe.naver.com/dbian/7717
 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com


[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

본 문서는 StartUP Tuning(for MySQL) 강의의 일부를 책의 서술 형태로 정리한 문서입니다.

 

지난 글에서는 SQL 성능 문제를 인덱스로 해결했습니다. ( https://sweetquant.tistory.com/555 )

인덱스를 마스터하기 위해서는 많은 시간과 노력이 필요합니다. 인덱스를 본격적으로 공부하기에 앞서 인덱스의 개념에 대해 간단히 알아볼 필요가 있습니다.


"데이터를 정렬해 라벨링하고, 라벨을 참고해 원하는 데이터를 빠르게 찾는다"
이것이 바로 인덱스의 개념입니다.

 

INDEX 개념잡기


DBMS: MySQL 8.0.35

SQL에 성능 문제를 해결하기 위해서 가장 먼저 할 일은 실행계획을 확인하는 것입니다.

실행계획을 통해 Table scan과 같은 테이블 전체를 검색하는 작업을 발견하면, 인덱스(INDEX)를 생성해 테이블 전체 검색이 아닌 인덱스를 이용한 데이터 검색으로 SQL이 처리되도록 유도할 수 있습니다.

그러나, 이러한 단순한 사실만 알고 인덱스를 적용해서는 SQL 성능 개선을 제대로 할 수 없습니다.

실제로 인덱스를 만들어도 성능 개선 효과가 없거나 오히려 역효과가 나는 경우도 있습니다.

인덱스를 통한 성능 개선 효과가 있는지 판단하기 위해서는 인덱스의 개념과 물리적인 구조도 이해하고 있어야 합니다.


[Tip]
느린 SQL의 성능 개선 방법에는 인덱스만 있는 것은 아닙니다. 인덱스는 다양한 성능 개선 방법을 익히기 위한 시작점일 뿐입니다.


 

우리는 가장 먼저 인덱스의 개념을 이해할 필요가 있습니다. 회사에 아래 그림 좌측과 같이 12개의 거래처가 있다고 가정해봅시다. 12개의 거래처 관련된 문서를 거래처 서류함에 보관하려고 합니다.


 
회사의 팀장이 ‘나엉망’ 직원에게 거래처 서류를 정리하라고 지시했습니다.

‘나엉망’ 직원은 빨리 정리하고 쉬기 위해서 무작위로 서류를 세 개씩 나누어서 서류함의 네 개 서랍에 나누어 넣었습니다. 무작위로 서류를 서랍에 넣었으므로 결과적으로 필요한 서류가 어느 서랍에 있는지는 알 수가 없게 되었습니다. 다시 말해, Airbnb 서류가 어느 서랍에 있을지는 알 수 없습니다. Airbnb 서류를 찾기 위해서는 서류함의 서랍을 하나씩 열어봐야 합니다. 운이 좋으면 첫 번째 서랍에서 찾을 수도 있고, 운이 나쁘면 네 번째 서랍에서 서류를 발견하게 될 것입니다. 다른 거래처의 서류도 마찬가지입니다. 그날의 운에 따라 서류를 빨리 찾거나 늦게 찾거나 하는 것이죠.


이러한 상황을 알게 팀장은 이번에는 ‘나깔끔’ 직원을 불러 서류를 다시 정리하라고 지시했습니다.

‘나깔끔’직원은 모든 서류를 꺼낸 후에 알파벳 순으로 정렬을 한 후에, 알파벳 순서대로 거래처를 세 개씩 나누고 서랍에 차례대로 넣었습니다. 그리고 서랍 앞에는 어떤 알파벳으로 시작하는 거래처 서류가 있는지 알아 볼 수 있도록 라벨링을 했습니다. 다음 그림과 같이 말이죠.

 


 

이와 같이 정리를 해 놓으니, 서랍을 한 번만 열면 원하는 서류를 찾을 수 있습니다. Airbnb는 (A)로 시작하므로 1번 서랍을 열면 바로 찾을 수 있습니다. Samsung 서류는 (N)과 (T) 사이에 있으므로 3번 서랍을 열만 바로 찾을 수 있습니다.
이처럼 데이터를 정렬하고 라벨링을 해서, 원하는 데이터를 빠르게 찾을 수 있도록 도움 주는 객체가 바로 인덱스입니다.

 

인덱스는 일반적으로 삼각형 모양으로 표현합니다. 서류함을 삼각형의 위쪽 꼭지점으로, 서랍 안에 들어가 있는 서류들을 삼각형의 밑면으로 표현할 수 있습니다. 아래 그림과 같이 말이죠.

 

인덱스는 실제 B Tree 자료 구조로 구현되어 있으며 B Tree에서의 데이터 검색을 효과적으로 설명하기 위해 이와 같은 이와 같은 삼각형 모양을 자주 사용하게 됩니다.


인덱스의 개념을 간단히 살펴봤습니다. 인덱스를 제대로 사용하기 위한 첫 단추를 잠근 것입니다. 인덱스를 마스터하기 위해서는 앞으로 인덱스의 구조도 알아야 하며, SQL에 따라 인덱스 탐색이 어떻게 되는지, 그리고 인덱스의 종류도 공부해야 합니다.
인덱스 개념만 공부한 채로 섣부르게 인덱스를 만들게 되면 큰 문제를 겪을 수 있습니다.

SQL 경력이 20년이 넘는 저 역시도 여전히 인덱스를 만드는 일은 항상 걱정이 앞서는 일이기도 합니다.

인덱스는 어떤 SQL의 성능에는 도움이 되기도 하지만, 어떤 SQL의 성능에는 악영향을 줄 수도 있기 때문입니다.

항상 인덱스 추가, 변경은 긴장되는 일이랍니다.

시간을 가지고 인덱스와 SQL의 성능에 대해 더 공부해보신후 인덱스 적용을 고민해보시기 바랍니다.

 

 

PDF 다운로드

20240429_StartUPTuning_인덱스개념.pdf
0.45MB


[StartUP Tuning]

 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

 

[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

 

글 하단 부분에서 별도 pdf로 다운로드 받으실 수 있습니다.

 

MySQL의 EXPLAIN ANALYZE 읽어보기 #2

 

DBMS: MySQL 8.0.35

지난 글에서는 MySQL의 실제 실행계획을 살펴봤습니다.

https://sweetquant.tistory.com/553

 

MySQL EXPLAIN ANALYZE

MySQL의 EXPLAIN ANALYZE 읽어보기 테스트 DBMS: MySQL 8.0.35 본 문서는 StartUP Tuning(for MySQL) 강의의 일부를 책의 서술 형태로 정리한 문서입니다. 가장 아래에 PDF 버젼으로도 첨부드리니 필요하신 분은 다

sweetquant.tistory.com

 

그리고 지난 글 마지막에 SQL의 가장 큰 문제가 어디인지 스스로 진단해보기를 부탁드렸습니다. 지난 글에서 설명한 SQL과 실행계획은 다음과 같습니다.

EXPLAIN ANALYZE
SELECT T1.CUS_ID ,COUNT(*) CNT
FROM   T_ORD_BIG T1 
WHERE  T1.ORD_DT = STR_TO_DATE('20170103','%Y%m%d')
GROUP BY T1.CUS_ID;

1 -> Table scan on <temporary>  (actual time=5992..5992 rows=9 loops=1)
2     -> Aggregate using temporary table  (actual time=5992..5992 rows=9 loops=1)
3         -> Filter: (t1.ORD_DT = ('20170103')) (actual time=35.4..5985 rows=18000 loops=1)
4             -> Table scan on T1 (actual time=0.0889..5303 rows=6.09e+6 loops=1)



라인 번호 기준으로 4->3->2->1의 흐름으로 SQL이 처리되는데, 전체 실행 시간이 5.9초 정도입니다.

이 중에 4번과 3번 라인의 Table scan과 Filter가 대부분의 실행 시간을 차지하고 있습니다.

또한, 4번 단계에서 처리한 데이터 건수가 6.09e+6(6,090,000)이었으나 3번 단계에서 18,000건으로 매우 많이 줄어 든 것을 알 수 있습니다.

이러한 정보를 종합해 보면, 4번과 3번 단계를 처리하는 과정이 성능 문제의 중심이란 것을 알 수 있습니다.

 

어디가 아픈지는 알았으니 이제 치료를 해야 하는데, 치료를 하기 위해서는 기본적인 치료법을 알고 있어야 합니다.

아픈 SQL을 치료하는 방법은 매우 다양합니다.

그 중에 Table scan(TABLE FULL SCAN)이란 질병이 있는 SQL은 인덱스(INDEX)라는 처방이 필요합니다.

이 인덱스란 치료를 처방하기 위해서는 인덱스의 구조와 인덱스를 이용해 데이터를 찾는 과정에 대한 지식이 필요합니다.

이는 별도로 길게 다루어야 할 내용입니다. 그러므로 지금은 인덱스를 만들어 효과가 있는지 정도만 살펴보도록 하겠습니다.

SQL을 보면 WHERE 절에 ORD_DT에 대한 조건이 있습니다. 그리고 실행계획의 3번 라인을 살펴보면 Filter 조건으로 ORD_DT가 사용되고 있습니다. 이는 실행계획에서 Filter 부분이 SQL의 WHERE 절을 처리한 것이라는 뜻입니다. 인덱스는 기본적으로 Filter된 컬럼에 대해 구성합니다.

아래 SQL로 인덱스를 추가합니다.

CREATE INDEX T_ORD_BIG_X01 ON T_ORD_BIG(ORD_DT);

 


[Tip]
인덱스를 만드는 작업은 DB내 자원을 제법 사용합니다. 해당 테이블에 부하가 걸리기도 합니다. 실제 인덱스를 만들어본 경험이 없으신 분은 개발 DB에서 충분한 테스트를 해보기 바랍니다. 운영 DB에서 인덱스를 만들 때는 사용자가 가장 적은 시간을 이용하는 것을 권장합니다.



인덱스를 만들고, 이전 SQL을 다시 실행해 실제 실행계획을 추출해봅니다. 아래와 같습니다.

EXPLAIN ANALYZE
SELECT T1.CUS_ID ,COUNT(*) CNT
FROM   T_ORD_BIG T1 
WHERE  T1.ORD_DT = STR_TO_DATE('20170103','%Y%m%d')
GROUP BY T1.CUS_ID;

1 -> Table scan on <temporary>  (actual time=38.2..38.2 rows=9 loops=1)
2    -> Aggregate using temporary table  (actual time=38.2..38.2 rows=9 loops=1)
3      -> Index lookup on T1 using T_ORD_BIG_X01 (ORD_DT= '20170103') (actual time=0.521..26.1 rows=18000 loops=1)

 

인덱스를 만들어준 것만으로 기존 5.9초였던 실행 시간이 0.038초로 개선되었습니다.

실행계획을 살펴보면 네 개의 단계였던 실행계획이 세 개의 단계로 줄어든 것을 알 수 있습니다.

주의 깊게 볼 것은 3번 라인의 Index Lookup입니다. 이전 실행계획에 있던 Table scan과 Filter가 사라지고 Index Lookup이 나타났습니다. Index Lookup은 WHERE 절의 동등(=) 조건에 해당하는 데이터를 인덱스를 사용해 찾아낸 경우에 나타나는 작업입니다.

Index Lookup의 actual 항목을 살펴보면 처리한 시간이 0.521..26.1ms로 매우 작습니다. 또한 인덱스로 처리한 건수(rows)가 18,000 건으로 SQL 결과를 얻어내는데 필요한 만큼의 데이터만 읽은 것입니다.

다시 말해, 불필요한 데이터에 대한 접근 없이 SQL이 처리된 것입니다.

 

이처럼 인덱스가 없는 SQL은 인덱스를 만드는 것만으로 성능 개선 효과가 나타날 수 있습니다.

물론 무조건 인덱스를 만든다고 성능 개선이 되는 것은 아닙니다. 경우에 따라서는 생성한 인덱스가 아무 효과가 없을 수도 있으며, 오히려 역효과가 날 수도 있습니다.

 

인덱스는 SQL 성능 개선을 위한 많은 방법 중에 하나입니다.

앞에서도 설명 드렸듯이 SQL의 성능 문제를 해결하기 위해 가장 먼저 할 일은 실행계획을 살펴보는 것입니다.

실행계획으로 현재 아픈 곳을 찾아내 진단하고, 현재 SQL과 테이블 구조(현재 인덱스, 컬럼 구성, 데이터 양, 테이블 간의 관계 등)를 고민해 그에 맞는 적절한 진료를 해야 합니다.


오늘 준비한 글은 여기까지입니다. 감사합니다.

 

아래는 실제 강의에서 해당 과정을 설명하는 슬라이드입니다.

 

 

 

아래는 현재 글을 pdf로 만든 자료입니다.

20240429_StartUPTuning_실행계획2.pdf
0.33MB

 

 


[StartUP Tuning]

  • SQL 입문을 넘어선 MySQL을 활용한 SQL 튜닝 입문 교육
  • 2024년 5월 주말 오프라인 교육 과정을 모집중: https://cafe.naver.com/dbian/7717
 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

MySQL을 활용한 SQL 튜닝 입문. StartUP Tuning의 24년 5월 교육 교재의 목차를 소개합니다.

이번에도 375장의 슬라이드로 두툼한 두께를 자랑합니다. 이 중에 BOOSTER QUIZ는 46개입니다.

교육 수강생 분들께 제본 교재를 제공해드립니다.

(제본 교재는 A4 한 페이지에 두 개의 슬라이드로 구성되어 있습니다.)

 

MySQL의 성능 개선을 위한 첫 걸음, StartUP Tuning으로 시작해보시기 바랍니다.

 - 교육 신청: https://cafe.naver.com/dbian/7717

 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

 

주목차

1. 강의 소개
2. 실습환경 구성(MySQL)
3. 실습환경 구성(Maria)
5. 성능 기본 지식
6. 실행계획
7. INDEX 1
8. INDEX 2
9. INDEX와 성능 1
10. INDEX와 성능 2
11. INDEX와 성능 3
12. ORDER BY
13. JOIN의 내부 처리 방식
14. HINT
15. JOIN과 성능
16. 맛보기 튜닝
17. Paging SQL
18. INDEX 설계
19. 성능 수집
20. 파티션
21. Transaction
22. SQL GUIDE

 

상세 목차

1. 강의 소개
    1. ERD: MYTUNDB 논리(Logical)
    1. ERD: MYTUNDB 물리(Physical)
    1. 강사 소개
    1. DBian 도서 소개
    1. StartUP Tuning
    1. 차례
2. 실습환경 구성(MySQL)
    2. 완성된 실습 환경
    2. MySQL 다운로드
    2. MySQL 다운로드: Windows MySQL 8.0.35
    2. MySQL 다운로드: MAC MySQL 8.0.35 다운로드
    2. 기존 MySQL Upgrade / Remove 선택
    2. Choosing a setup Type
    2. Check Requirements
    2. Installation
    2. Product Configuration / Type and Networking
    2. Authentication Method / Accounts and Roles
    2. Windows Service / Server File Permissions
    2. Apply Configuration
    2. MySQL Router Configuration / Connect To Server
    2. Apply Configuration
    2. Installation Complete
    2. Workbench 접속 #1
    2. Workbench 접속 #2
    2. Workbench 접속 #3
    2. Hello SQL
    2. Workbench 필요한 환경 설정 #1
    2. Workbench 필요한 환경 설정 #2
    2. Dbeaver
    2. SQL Tool
3. 실습환경 구성(Maria)
    3. 다운로드
    3. 완성된 실습 환경
    3. MariaDB 설치
    3. HeidiSQL
    3. Dbeaver
    3. Hello SQL
    4. 실습 데이터베이스 생성
    4. CREATE DATABASE
    4. 기본 데이터베이스 설정
    4. 캐릭터셋 확인
    4. 테이블 및 데이터 생성
5. 성능 기본 지식
    5. SQL 튜닝이란?
    5. SQL 성능 개선의 주요 요소
    5. 비효율 SQL이란?
    5. SQL 처리 과정
    5. Execution Plan과 Optimizer #1
    5. Execution Plan과 Optimizer #2
    5. Execution Plan과 Optimizer #3
    5. Statistics #1
    5. Statistics #2
    5. Statistics #3
    5. Storage Engine
    5. Oracle VS. MySQL
    5. IO
    5. 물리적 IO와 논리적 IO #1
    5. 물리적 IO와 논리적 IO #2
    5. Buffer pool size 변경하기
    5. SQL 성능 개선 프로세스
    5. 지속적인 SQL 성능 개선 필요성
6. 실행계획
    6. 인덱스 초기화
    6. EXPLAIN
    6. EXPLAIN 이해하기
    6. EXPLAIN 이해하기 – select_type
    6. EXPLAIN 이해하기 – 실행계획의 흐름 해석하기
    6. EXPLAIN 이해하기 – type(데이터 접근방식)
    6. EXPLAIN – Extra(옵티마이져 동작방식) 이해하기
    6. EXPLAIN FORMAT
    6. EXPLAIN FORMAT = TREE (MySQL)
    6. 실행한 SQL의 실제 접근 데이터 건수 측정
    6. 실행한 SQL의 요청 논리적IO 측정
    6. ANALYZE SQL(MariaDB)
    6. EXPLAIN ANALYZE #1 (MySQL)
    6. EXPLAIN ANALYZE #2 (MySQL)
    6. PROFILING
    6. 다른 세션의 실행계획 확인 (MySQL)
    BOOSTER QUIZ 6-1
7. INDEX 1
    7. INDEX란? 우선 읽어보자!
    7. 실행계획의 비효율을 찾아 INDEX로 해결하기 #1
    7. 실행계획의 비효율을 찾아 INDEX로 해결하기 #2
    7. 실행계획의 비효율을 찾아 INDEX로 해결하기 #3
    7. INDEX의 생성과 삭제
    7. INDEX 개념 잡기 #1
    7. INDEX 개념 잡기 #2
    7. B-Tree INDEX #1
    7. B-Tree INDEX #2
    7. 테이블 구조
    7. Heap 구조와 Table Scan(TABLE FULL SCAN)
    7. Heap과 INDEX #1
    7. Heap과 INDEX #2
    7. Heap과 INDEX #3
    7. Heap과 INDEX #4
    7. Heap과 INDEX #5
    7. 인덱스는 삼각형으로
    7. 인덱스 탐색 과정의 시각화 #1
    7. 인덱스 탐색 과정의 시각화 #2: CUS_ID 인덱스를 사용한 데이터 검색
    7. 인덱스 직접 그려보기
    7. CLUSTERED (INDEX) #1
    7. CLUSTERED (INDEX) #2
    7. CLUSTERED (INDEX) #3
    7. HEAP VS. CLUSTERED #1
    7. HEAP VS. CLUSTERED #2
8. INDEX 2
    8. 데이터 접근 방법
    8. 인덱스를 이용한 데이터 접근 #1
    8. 인덱스를 이용한 데이터 접근 #2: 인덱스 접근 시각화
    8. 인덱스를 이용한 데이터 접근 #3: INDEX LOOKUP
    8. 인덱스를 이용한 데이터 접근 #4: INDEX RANGE SCAN
    8. 인덱스를 이용한 데이터 접근 #5: COVERING INDEX (LOOKUP/RANGE SCAN)
    8. 인덱스를 이용한 데이터 접근 #6: INDEX SCAN(INDEX FULL SCAN)
    8. 인덱스를 이용한 데이터 접근 #7: 정리
    8. 테이블(클러스터드) 접근 #1
    8. 테이블(클러스터드) 접근 #2: 검색양에 따른 성능 변화
    8. 테이블(클러스터드) 접근 #3: 테이블 접근 횟수에 따른 성능 변화
    8. 테이블(클러스터드) 접근 #4: Covering Index
    8. 테이블(클러스터드) 접근 #5: 클러스터드 인덱스를 이용한 검색
    8. INDEX 확인하기 #1
    8. INDEX 확인하기 #2
    8. CLUSTERD INDEX에 대한 고민
    8. InnoDB가 제공하는 INDEX 구조
    8. INDEX 분류
    8. 조건에 따른 인덱스 선택
    BOOSTER QUIZ 8-1
    BOOSTER QUIZ 8-2
    BOOSTER QUIZ 8-3
    BOOSTER QUIZ 8-4
    BOOSTER QUIZ 8-5
9. INDEX와 성능 1
    9. 어느 컬럼에 인덱스를 만들 것인가? #1
    9. 어느 컬럼에 인덱스를 만들 것인가? #2
    9. 어느 컬럼에 인덱스를 만들 것인가? #3
    9. 어느 컬럼에 인덱스를 만들 것인가? #4: RNO를 제외한 조건은 어디서 처리되는가?
    BOOSTER QUIZ 9-1
    BOOSTER QUIZ 9-2
    BOOSTER QUIZ 9-3
    9. 공식만 외우지 말자 #1
    9. 공식만 외우지 말자 #2
10. INDEX와 성능 2
    10. 단일 인덱스 VS. 복합 인덱스 #1
    10. 단일 인덱스 VS. 복합 인덱스 #2
    10. 단일 인덱스 VS. 복합 인덱스 #3
    10. 단일 인덱스 VS. 복합 인덱스 #4
    10. 단일 인덱스 VS. 복합 인덱스 #5
    10. 단일 인덱스 VS. 복합 인덱스 #6: 오라클의 실행계획
    BOOSTER QUIZ 10-1
    10. 복합 인덱스의 컬럼 순서
    10. 복합 인덱스 컬럼 순서에 따른 성능 차이 #1
    10. 복합 인덱스 컬럼 순서에 따른 성능 차이 #2
    10. 복합 인덱스 컬럼 순서에 따른 성능 차이 #3
    10. 복합 인덱스 컬럼 순서에 따른 성능 차이 #4
    BOOSTER QUIZ 10-2
    BOOSTER QUIZ 10-3
    BOOSTER QUIZ 10-4
    10. 복합 인덱스의 선두 조건 누락
    10. 복합 인덱스 컬럼 선정과 순서 #1
    10. 복합 인덱스 컬럼 선정과 순서 #2
    10. 복합 인덱스 컬럼 선정과 순서 #4
    BOOSTER QUIZ 10-5
    BOOSTER QUIZ 10-6
    BOOSTER QUIZ 10-7
    BOOSTER QUIZ 10-8
    10. 복합 인덱스 정리
11. INDEX와 성능 3
    11. 인덱스를 제대로 활용할 수 없는 SQL #1
    11. 인덱스를 제대로 활용할 수 없는 SQL #2
    BOOSTER QUIZ 11-1
    BOOSTER QUIZ 11-2
    11. Index Covering(Covered Index) #1
    11. Index Covering(Covered Index) #2
    BOOSTER QUIZ 11-3
    11. 복합 인덱스의 선두 조건 누락 #1
    11. 복합 인덱스의 선두 조건 누락 #2
    11. 복합 인덱스의 선두 조건 누락 #3
    11. 복합 인덱스의 선두 조건 누락 #4 – Index Skip Scan
    BOOSTER QUIZ 11-4
    11. 언제까지 인덱스를 탈 것만 같아? #1
    11. 언제까지 인덱스를 탈 것만 같아? #2
    11. 언제까지 인덱스를 탈 것만 같아? #3
    11. 너무 많은 인덱스의 위험성
    11. 클러스터드 인덱스의 크기
    11. INDEX란? 한 번 더 읽어보자!
    BOOSTER QUIZ 11-5
12. ORDER BY
    12. 비효율 찾기
    12. Using filesort
    12. Using filesort 제거하기
    12. sort buffer size
    12. INDEX RANGE SCAN - ASC
    12. INDEX RANGE SCAN - DESC
    12. INDEX RANGE SCAN – 정렬과 무관하게 인덱스를 사용하면?
    12. ORDER BY LIMIT n
    12. ORDER BY SQL을 위한 인덱스 전략 #1
    12. ORDER BY SQL을 위한 인덱스 전략 #2
    12. ORDER BY SQL을 위한 인덱스 전략 #3
    BOOSTER QUIZ 12-1
    BOOSTER QUIZ 12-2
13. JOIN의 내부 처리 방식
    13. JOIN의 내부 처리 방식
    13. NL JOIN 이해하기 #1
    13. NL JOIN 이해하기 #2
    13. HASH JOIN 이해하기 #1
    13. HASH JOIN 이해하기 #2
    13. HASH JOIN 이해하기 #1 (MariaDB)
    13. HASH JOIN 이해하기 #2 (MariaDB)
    13. HASH JOIN 이해하기 #3 (MariaDB)
    13. HASH JOIN 이해하기 #4 (MariaDB)
    13. HASH JOIN 이해하기 #1 (MySQL)
    13. HASH JOIN 이해하기 #2 (MySQL)
    BOOSTER QUIZ 13-1
    BOOSTER QUIZ 13-2
14. HINT
    14. Optimizer Hints
    14. 인덱스 힌트
    14. JOIN_ORDER #1
    14. JOIN_ORDER #2
    14. JOIN_ORDER 와 JOIN 방법 제어
15. JOIN과 성능
    15. NL JOIN 튜닝 – 선행접근과 후행접근
    15. NL JOIN 튜닝 – 후행접근 조인 컬럼의 인덱스 유무 #1
    15. NL JOIN 튜닝 – 후행접근 조인 컬럼의 인덱스 유무 #2
    15. NL JOIN 튜닝 – 후행접근 조인 컬럼의 인덱스 유무 #4
    15. NL JOIN 튜닝 – 후행접근 조인 컬럼의 인덱스 유무 #4
    15. NL JOIN 튜닝 – 후행접근 조인 컬럼의 인덱스 유무 #5
    15. NL JOIN 튜닝 – 후행접근 조인 컬럼의 인덱스 유무 #6
    15. NL JOIN 튜닝 – 후행접근 조인 컬럼의 인덱스 유무 #7
    15. NL JOIN 튜닝 – join_cache_level (MariaDB)
    BOOSTER QUIZ 15-1
    BOOSTER QUIZ 15-2
    15. NL JOIN 튜닝 – 조인 순서 #1
    15. NL JOIN 튜닝 – 조인 순서 #2
    15. NL JOIN 튜닝 – 조인 순서 #3
    15. NL JOIN 튜닝 – 조인 순서 #4
    15. NL JOIN 튜닝 – 조인 순서 #5
    BOOSTER QUIZ 15-3
    15. NL JOIN 튜닝 – 여러 테이블의 조인 #1
    15. NL JOIN 튜닝 – 여러 테이블의 조인 #2
    15. NL JOIN 튜닝 – 여러 테이블의 조인 #3
    15. NL JOIN 튜닝 – 여러 테이블의 조인 #4
    15. HASH JOIN 튜닝 – Build Input 선택 #1 (MariaDB)
    15. HASH JOIN 튜닝 – Build Input 선택 #2 (MariaDB)
    15. HASH JOIN 튜닝 – Build Input 선택 #1 (MySQL)
    15. HASH JOIN 튜닝 – Build Input 선택 #2 (MySQL)
    15. HASH JOIN 튜닝 – 인덱스
    BOOSTER QUIZ 15-4
    BOOSTER QUIZ 15-5
    15. JOIN과 성능 Summary

16. 맛보기 튜닝
    16. 특정 고객의 마지막 주문 일자 구하기 #1
    16. 특정 고객의 마지막 주문 일자 구하기 #2
    16. 특정 고객의 마지막 주문 일자 구하기 #3
    BOOSTER QUIZ 16-1
    16. 여러 고객의 마지막 주문 일자: 서브쿼리 #1
    16. 여러 고객의 마지막 주문 일자: 서브쿼리 #2
    16. 불필요한 카운트
    16. Materialize #1
    16. Materialize #2: SQL 변경과 NO_MERGE
    16. Materialize #3: SQL 변경
    BOOSTER QUIZ 16-2
    16. 무리한 스칼라 서브쿼리
    BOOSTER QUIZ 16-3
    16. WHERE 절 서브쿼리의 순환조건 #1
    16. WHERE 절 서브쿼리의 순환조건 #2
    16. WHERE 절 서브쿼리의 순환조건 #3
    BOOSTER QUIZ 16-4
    16. WHERE 절 서브쿼리의 순환조건: 마지막 데이터 & 빅 테이블 #1
    16. WHERE 절 서브쿼리의 순환조건: 마지막 데이터 & 빅 테이블 #2
    BOOSTER QUIZ 16-5
    BOOSTER QUIZ 16-6
    16. QUERY TRANSFORMATION
    16. 조건 공급 #1
    16. 조건 공급 #2
    16. 조건 공급 #3
    16. 조건 공급 #4
    16. 적절하지 않은 조건 공급
    BOOSTER QUIZ 16-7
    BOOSTER QUIZ 16-8
    16. MySQL의 강력한 무기 Using index for group by #1
    16. MySQL의 강력한 무기 Using index for group by #2
    16. MySQL의 강력한 무기 Using index for group by #3
    16. MySQL의 강력한 무기 Using index for group by #4
    16. MySQL의 강력한 무기 Using index for group by #5
    BOOSTER QUIZ 16-9
    BOOSTER QUIZ 16-10
    BOOSTER QUIZ 16-11
    16. 날짜 테이블 #1
    16. 날짜 테이블 #2
    16. 날짜 테이블 #3
    BOOSTER QUIZ 16-12
    16. 값의 분포도를 생각하자 #1
    16. 값의 분포도를 고려 #2
    16. 조인을 추가한 복합 인덱스 활용 #1: 날짜 조건 누락(개선 전)
    16. 조인을 추가한 복합 인덱스 활용 #2 : 날짜 조건 누락(개선 후)
    16. 조인을 추가한 복합 인덱스 활용 #1: 회원ID 누락(개선 전)
    16. 조인을 추가한 복합 인덱스 활용 #2: 회원ID 누락(개선 후)
17. Paging SQL
    17. 페이징의 종류
    17. WAS 페이징
    17. DB 페이징 #1
    17. DB 페이징 #2
    17. DB-INDEX 페이징 #1
    17. DB-INDEX 페이징 #2
    17. DB-INDEX 페이징 #3
    17. DB-INDEX 페이징 #4
    17. 조인 SQL의 DB-INDEX 페이징 #1
    17. 조인 SQL의 DB-INDEX 페이징 #2
    17. DB-INDEX 페이징 유지의 어려움
    BOOSTER QUIZ 17-1
    BOOSTER QUIZ 17-1
18. INDEX 설계
    18. INDEX 설계
    18. INDEX 설계 과정
    BOOSTER QUIZ 18-1
19. 성능 수집
    19. SLOW Query 설정
    19. Performance Schema
    19. 성능 관련 주요 VIEW
20. 파티션
    20. 파티션 개념 #1
    20. 파티션 개념 #2
    20. 파티션 개념 #3
    20. 파티션 개념 #3
    20. 파티션 만들기
    20. 파티션 성능 #1
    20. 파티션 성능 #2
    20. 파티션 성능 #3
21. Transaction
    21. Transaction
    21. ACID
    21. Isolation level
    21. MySQL과 MariaDB의 기본 Isolation level
    21. Isolation level 변경하기
    21. AUTO COMMIT
    21. 테스트 테이블 생성
    21. WAIT 테스트 #1
    21. WAIT 테스트 #2
    21. WAIT 테스트 #3
    21. 출금 테스트 #1
    21. 출금 테스트 #2
    21. 출금 테스트 #3
    21. 출금 테스트 #4
    21. Manual Commit 과 MetadataLock
    21. Isolation Level에 따른 테스트 #1
    21. Isolation Level에 따른 테스트 #2
22. SQL GUIDE
    22. SQL GUIDE의 목적
    22. 필수 SQL GUIDE - 01
    22. 필수 SQL GUIDE - 02
    22. 필수 SQL GUIDE - 03
    22. 필수 SQL GUIDE - 04
    22. 필수 SQL GUIDE - 05
    22. 필수 SQL GUIDE - 06
    22. 필수 SQL GUIDE - 07
    22. 필수 SQL GUIDE - 08
    22. 필수 SQL GUIDE - 09
    22. 필수 SQL GUIDE - 10
    22. 필수 SQL GUIDE - 11
    22. 필수 SQL GUIDE - 12
    22. 필수 SQL GUIDE - 13
    22. 권장 SQL GUIDE - 01
    22. 권장 SQL GUIDE - 02
    22. 권장 SQL GUIDE - 03
    22. 권장 SQL GUIDE - 04
    22. 권장 SQL GUIDE - 05
    22. 권장 SQL GUIDE - 06
    22. 권장 SQL GUIDE - 07
    22. 권장 SQL GUIDE - 08
    22. 권장 SQL GUIDE - 09
    22. 권장 SQL GUIDE - 10
    22. 권장 SQL GUIDE - 11

 

 

 

 

MySQL의 EXPLAIN ANALYZE 읽어보기

 

테스트 DBMS: MySQL 8.0.35

 

본 문서는 StartUP Tuning(for MySQL) 강의의 일부를 책의 서술 형태로 정리한 문서입니다. 가장 아래에 PDF 버젼으로도 첨부드리니 필요하신 분은 다운 받아가시기 바랍니다.

 


SQL의 성능에 문제가 있을 때 우리가 가장 먼저 할 일은 실행계획을 살펴보는 것입니다. MySQL은 8버전부터 EXPLAIN ANALYZE 기능을 지원합니다. EXPLAIN ANALYZE는 “실제 실행된” SQL의 실행계획을 Tree 형태로 보여줍니다. 실제 실행계획은 SQL 성능 개선할 때 매우 유용한 기능입니다.
아래 SQL은 T_ORD_BIG 테이블에서 특정 일자의 데이터를 조회해 고객ID(CUS_ID)별 주문 건수를 구하는 SQL입니다. EXPLAIN ANALYZE를 사용했으므로 SQL의 실행 결과가 아닌 SQL을 처리한 과정에 해당하는 실행계획을 결과로 얻을 수 있습니다.

EXPLAIN ANALYZE
SELECT T1.CUS_ID ,COUNT(*) CNT
FROM   T_ORD_BIG T1 
WHERE  T1.ORD_DT = STR_TO_DATE('20170103','%Y%m%d')
GROUP BY T1.CUS_ID;

 

위 SQL을 실행하면 약 5.9초 정도의 시간이 걸리며, 아래와 같은 실제 실행계획이 출력됩니다. (지면상 실행계획의 일부 내용은 생략했습니다.)

-> Table scan on <temporary>  (actual time=5992..5992 rows=9 loops=1)
    -> Aggregate using temporary table  (actual time=5992..5992 rows=9 loops=1)
        -> Filter: (t1.ORD_DT = ('20170103')) (actual time=35.4..5985 rows=18000 loops=1)
            -> Table scan on T1 (actual time=0.0889..5303 rows=6.09e+6 loops=1)

 

Tree 형태의 실행계획은 일반적으로 가장 최하위 자식(Child) 단계부터 부모(Parent) 단계로 가면서 처리가 됩니다. 그러므로 위 실행계획의 흐름은 4->3->2->1 순서가 됩니다.

 


[Tip]
실행계획은 SQL의 내부적인 처리 흐름을 보여줄 뿐, 실제 DB 내부적인 처리 순서를 완벽하게 표현해주지는 않습니다.
4->3->2->1이란 순서가 4가 완료된 후 3이 실행되고, 3이 완료되면 2가 실행된다고 말하기는 어렵습니다.
4가 완료된 후 3이 처리되었을 수도 있으며, 4가 처리되면서 3이 동시에 처리될 수도 있습니다.
실행계획을 통해 내부적인 처리 순서를 완벽히 파악하기 보다는 전반적인 흐름을 이해하는 것에 초점을 맞추는 것이 좋습니다.


 

실행 계획의 처리 흐름대로 따라가면서 각 단계를 하나씩 살펴보도록 하겠습니다

 

4번 라인: Table scan on T1

가장 첫 번째 단계인 4번 라인을 보면, Table scan이란 작업이 실행되고 있습니다.

Table scan이란 테이블 전체를 검색하는 것을 뜻합니다. 테이블에 1억 건이 있다면 1억 건 전부를, 10억 건이 있다면 10억 건 전부를 검색했음을 뜻합니다.

Table scan 뒤에는 대상 테이블의 별칭이 적혀 있습니다.

현재 실행계획에는 Table scan on T1 이라고 표시되어 있습니다. 실행한 SQL의 FROM 절에서 T_ORD_BIG에 T1이란 별칭을 사용했습니다. 그러므로 Table scan의 대상이 T_ORD_BIG임을 알 수 있습니다.

감사하게도 실제 실행계획에는 해당 단계별로 수행된 시간과 처리한 건수의 정보를 actual 항목에 표시해 줍니다. 이와 같은 실제 처리된 정보는 SQL 튜닝에 매우 유용합니다. 4번 라인의 Table scan의 actual 정보는 다음과 같습니다.

  • Table scan on T1 (actual time=0.0889..5303 rows=6.09e+6 loops=1)

actual의 time 부분을 살펴보면 0.0859..5303로 표시되어 있습니다.

이는 해당 단계가 0.0859ms에 시작해 5303ms에 종료되었음을 뜻합니다. 5303ms는 약 5.3초입니다. 위 SQL은 총 실행 시간이 5.9초 정도가 걸립니다. 그 중에 4번 라인의 Table scan이 5.3초로 대부분을 차지하고 있는 상황입니다.

actual 항목 중에 rows 부분도 주의 깊게 살펴봐야 합니다. rows는 해당 단계가 끝났을 때 추출된 실제 데이터 건수입니다.

여기에는 6.09e+6이라고 표시되어 있습니다. 이는 과학적 표기법(또는 지수 표기법) 형태의 수치로서 구글이나 GPT를 통해 일반적인 숫자로 환산해보면 6,090,000 입니다. 다시 말해 Table scan 단계에서 추출된 데이터는 6,090,000 건입니다.

이 수치는 정확히 T_ORD_BIG의 현재 데이터 건 수와 일치합니다. Table Scan에서 테이블 전체 데이터를 읽었다는 것을 알 수 있으며, 이 과정이 5.3초 정도가 걸렸음을 알 수 있습니다.

 


3번 라인: Filter

Table scan을 거쳐 다음 실행되는 단계는 3번 라인의 Filter입니다. Filter는 특정 조건을 사용해 데이터를 걸러내는 처리를 하는 작업입니다.

MySQL의 Filter 단계에는 Filter로 사용된 조건이 같이 표시됩니다. 3번 라인의 실행계획을 통해 ORD_DT 조건에 대해 Filter가 처리된 것을 알 수 있습니다.

  • Filter: (t1.ORD_DT = ('20170103')) (actual time=35.4..5985 rows=18000 loops=1)

 

actual 항목을 보면 time 부분이 35.4..5985입니다. 35.4ms에 시작해 5985ms에 해당 단계가 완료되었습니다. 처리되는 시간대가 4번 단계의 Table scan과 겹치는 것으로 보아 3번과 4번이 동시에 처리되는 작업임을 유추할 수 있습니다. 실제로도 테이블의 데이터를 검색하면서 Filter 작업이 동시에 이루어집니다. 다만, MySQL의 Tree 실행계획에서는 별도 단계로 표시해준 것입니다. 다른 DBMS의 경우는 3번과 4번 단계를 하나의 단계로 표현해주기도 합니다.

3번 단계의 rows를 보면 18,000입니다. 4번 단계의 rows는 6,090,000이었습니다. 4번->3번 흐름으로 SQL이 처리되므로 6,090,000 건의 데이터에 접근해 결과적으로 18,000 건만 남았다고 해석할 수 있습니다. 이를 역산해보면 6,072,000 건((6,090,000-18,000)의 데이터가 4번에서 3번 단계를 거치면서 버려진 것입니다. 버려졌다는 것은 SQL 결과를 만드는데 불필요하다는 뜻입니다.

그러므로 이러한 불필요한 접근을 줄일 수 있다면 SQL 성능이 개선될 수 있습니다. 이는 다음 번에 이야기하기로 하고 계속해서 실행계획을 읽어 나가도록 하겠습니다.

 

2번 라인: Aggregate

2번 라인의 Aggregate는 데이터를 집계 처리하는 작업입니다.

  • Aggregate using temporary table  (actual time=5992..5992 rows=9 loops=1)

 

현재 우리가 실행한 SQL에는 “GROUP BY T1.CUS_ID”가 포함되어 있습니다. 그러므로 DB 내부적으로 Aggregate 작업을 거쳐 집계된(GROUP BY) 결과를 만들어냅니다. actual 항목의 time을 보면  5992..5992로 5.9초에 시작해 5.9초에 끝난 것을 알 수 있습니다. 시작과 종료 시간이 0.000초로 매우 빨리 처리된 것입니다.

Aggregate를 거쳐 만들어진 결과 건수는 9입니다. actual의 rows를 보면 알 수 있습니다. Aggregate의 결과는 9건이지만, Aggregate를 수행한 대상 건수는 몇 건일까요? 바로 이전 실행 단계인 3번 라인의 Filter의 rows에 그 정답이 있습니다. 3번 라인의 Filter의 rows는 18,000 이었습니다. 그러므로 18,000 건의 데이터가 Aggregate 작업으로 공급되었으며, 18,000 건의 데이터를 집계해 9 건의 결과를 만든 것입니다.

이처럼 rows 항목은 이전 단계와 비교해 보는 것이 좋습니다. 각 실행 단계를 거치면서 데이터 양이 어떻게 변하는지 추적할 수 있으며, 이를 통해 과도한 데이터 흐름이 있는 단계를 찾아낼 수 있습니다.


1번 라인: Table scan on <temporary>

1번 라인의 처리 내용을 살펴보면 4번 라인과 마찬가지로 Table scan을 하고 있습니다.

  • Table scan on <temporary>  (actual time=5992..5992 rows=9 loops=1)

다만 1번 라인의 Table scan 대상은 <temporary>라는 임시 테이블입니다. 이 임시 테이블은 2번 라인의 Aggregate를 거쳐 내부적으로 만들어진 테이블입니다. Aggregate 단계에서 9건의 데이터가 만들어졌으므로 <temporary>에는 당연히 9 건의 데이터만 담겨 있습니다. 9건의 데이터를 Table scan하는 작업은 매우 빠릅니다.

사실 실행 계획의 가장 마지막 단계는 SQL의 최종 결과를 단순 출력하는 단계로 대부분의 경우 주의 깊게 볼 필요는 없습니다.

 

지금까지의 내용을 기억하면서 아래 SQL과 실행계획을 다시 한번 꼼꼼하게 살펴보시기 바랍니다. 어느 부분이 현재 SQL의 가장 큰 문제인지 진단해볼 수 있을까요? 해결법은 찾지 못하더라도, 어느 부분이 가장 문제가 있다고 말할 수는 있어야 합니다.

EXPLAIN ANALYZE
SELECT T1.CUS_ID ,COUNT(*) CNT
FROM   T_ORD_BIG T1 
WHERE  T1.ORD_DT = STR_TO_DATE('20170103','%Y%m%d')
GROUP BY T1.CUS_ID;
-> Table scan on <temporary>  (actual time=5992..5992 rows=9 loops=1)
    -> Aggregate using temporary table  (actual time=5992..5992 rows=9 loops=1)
        -> Filter: (t1.ORD_DT = ('20170103')) (actual time=35.4..5985 rows=18000 loops=1)
            -> Table scan on T1 (actual time=0.0889..5303 rows=6.09e+6 loops=1)


해결법은 기회가 된다면 다음 글에 이어서 적어보도록 하겠습니다. 감사합니다.

 

아래는 지금까지의 내용을 PDF로 정리한 문서입니다.

20240424_StartUPTuning_실행계획.pdf
0.35MB

 

 

StartUP Tuning 오프라인 강의에서는 지금까지 설명한 내용을 아래와 같은 슬라이드로 설명합니다.

 

 

 

[StartUP Tuning]

 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

[StartUP SQL]

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

이번 StartUP Tuning(MySQL을 활용한 SQL 튜닝 입문) 교재에 실릴 Booster Quiz입니다.

교육 앞 부분의 문제인만큼, 인덱스 구조만 이해하면 누구라도 풀수 있는 수준의 문제입니다.
교재에 직접 손으로 그려보면서, "아~ 인덱스가 이렇게 작동하는구나"를 느낄 수 있는 간단한 문제입니다.
("입문" 교육이라고 말씀을 드리긴 하지만, 교육 중반 정도 넘어가면 어려운 문제들이 나옵니다.)

교육은 언제나 진정성 있게 하자란 생각으로, 교재도 공을 들여 준비중입니다.

 

 

 

 


[StartUP Tuning]

  - SQL 입문을 넘어선 MySQL을 활용한 SQL 튜닝 입문 교육
  - 2024년 5월 오프라인 교육 과정 모집중: https://cafe.naver.com/dbian/7717

 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

 

[StartUP SQL]

  - 데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육

  - 교육용 슬라이드 전체 무료 오픈: https://sweetquant.tistory.com/497

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

 

 

 

오늘은 StartUP Tuning 강의 중 일부인 "언제까지 인덱스를 탈 것만 같아?" 부분을 소개해봅니다.

MySQL로 데이터를 조회할 때 언제까지 인덱스를 사용하는지, 언제나 인덱스가 좋은 것인지에 대한 내용입니다.


SQL의 성능을 위해서는 기본적으로 세 개의 요소가 필요합니다. StartUP Tuning에서는 아래와 같이 세 개의 요소를 정의합니다.

  • INDEX
  • 비효율 SQL 변경(제거)
  • 힌트 사용

이 외에도 SQL 성능을 위해 다양한 요소가 필요하겠지만 기본적으로 가장 신경써야 할 부분은 위의 세 가지입니다.

 

SQL 성능을 위해 인덱스를 잘 구성해야 합니다. 기본적인 인덱스 구성 없이 SQL 성능을 끌어 올리는 것은 불가능합니다.

그러나 인덱스가 잘 구성되어 있어도 SQL을 잘 작성하지 않는다면 아무 필요가 없습니다.

(StartUP Tuning 강의에서는 인덱스를 하루에 걸쳐 설명하지만, 항상 SQL의 중요성을 강조합니다.)

SQL이 실행되면 MySQL의 옵티마이져는 상황에 따라서 인덱스로 처리할지 테이블 FULL SCAN으로 처리할지 선택하게 됩니다. 이는 인덱스를 사용하는 것이 항상 성능에 유리하지는 않다는 뜻이기도 합니다.

 

아래와 같은 SQL의 조건을 변경해가면서 실행하면, 어느 지점부터 인덱스가 아닌 FULL SCAN을 선택하는지 간단히 살펴볼 수 있습니다. T_ORD_BIG에는 약 6백만건의 데이터가 존재하며 ORD_YMD 컬럼에 싱글 컬럼 인덱스가 존재합니다. SELECT 절에 일부러 인덱스에 없는 PAY_DT 컬럼을 사용해 인덱스를 사용한 후 테이블 접근이 발생하도록 유도했습니다. 

SELECT  MAX(T1.PAY_DT) MAX_PAY_DT, COUNT(*) CNT
FROM    T_ORD_BIG T1 
WHERE   T1.ORD_YMD >= '20170104'
AND     T1.ORD_YMD <  '20170110';

 

조회 조건을 변경해가면서 테스트를 해보면 아래와 같은 결과를 얻을 수 있습니다. 조회 건수가 450,000 건 정도가 되자 인덱스가 아닌 Table Scan(TABLE FULL SCAN)을 선택했습니다. (이는 인덱스로 데이터를 탐색 후 테이블 접근이 발생하는 것이 전제된 경우입니다. 만약에 테이블 접근 없이 인덱스만 사용한다면 다른 결과가 나올 것입니다.) 실행시간 역시 342,000건 까지는 1.75초 정도였으나 450,000건인 Table Scan부터는 7.05 초로 매우 느려진 것을 알 수 있습니다.

 

MySQL의 옵티마이져는 통계를 참고해 450,000건 정도부터는 인덱스보다는 Table Scan이 더 빠르다 판단한 것입니다. 

항상 옵티마이져가 최선의 선택을 하는 것은 아닙니다. 최선의 선택을 위해 주어진 환경에서 최대한 노력하지만, 최선의 선택이 아닐 수도 있습니다. 실제로 현재 환경에서 450,000건 정도는 Table Scan보다 인덱스를 활용한 처리가 더 빠릅니다. 위 결과를 시각화 해보면 다음과 같습니다. Table Scan(FULL SCAN)에서 Buffers(IO) 수치는 꺽이지만 실행 시간은 오히려 7초대까지 올라간 것을 알 수 있습니다.

 

여기서 주의할 점이 있습니다. 450,000이 Table Scan을 선택하는 일반화된 숫자가 절대 아니라는 점입니다. 이러한 숫자는 서버와 디스크 성능, 서버 설정, 테이블의 크기(로우x컬럼), 인덱스 구성, 통계, SQL문 등에 의해 다른 결과가 나올 수 있습니다. 제 개인 PC에 설치된 MySQL에서 이와 같은 수치가 나온 것이므로 각자 환경에서 큰 테이블을 기준으로 테스트 해보시기 바랍니다.

 

추가로 하나의 테스트를 더 해 봅니다. 조회 건수를 변경해가면서 INDEX 또는 NO_INDEX 힌트를 적용해 성능 비교를 하는 것입니다. 아래와 같은 결과를 얻을 수 있습니다.

 

450,000건을 처리할 때 인덱스를 사용한 경우에는 3.28초 정도의 시간이 걸린 것을 알 수 있습니다. 해당 건수의 FULL SCAN 시간은 6.64초 정도가 나왔습니다. (이전 테스트에서 7.05초 정도였습니다. 약간 시간이 줄어들었으나 크게 의미는 없습니다.)

위 내용을 시각화 해보면 다음과 같습니다.

 

Table Scan(FULL SCAN)은 몇 건의 데이터를 조회하든 거의 일정한 시간과 거의 일정한 IO를 유지합니다. 반면에 인덱스를 이용한 데이터 접근은 어느 순간(450,000 건을 넘어서는 순간)부터 IO와 실행시간이 급등하기 시작합니다.

이처럼 조회할 데이터가 많아질 수록 인덱스보다 Table Scan(FULL SCAN)이 SQL 성능을 위해 더 좋은 선택일 수 있습니다. (한번 더 강조하면, 이와 같은 수치는 테스트 환경에 따라 상이합니다.)

 

조회할 데이터가 많으면 Table Scan이 더 좋다! 그러나, SQL 튜닝에 많은 도움을 주시는 변동구 이사님께서 이런 말씀을 하셨습니다. "지금도 빠르고 앞으로도 빠를 것인가?"

현재 테스트한 T_ORD_BIG에는 6백만건 정도의 데이터가 있습니다.

데이터가 지금의 열 배가 된다면, 여전히 Table Scan(FULL SCAN)이 인덱스를 활용한 검색보다 빠를 수 있을지는 생각을 해볼 필요가 있습니다.

 

StartUP Tuning(MySQL을 활용한 SQL 튜닝 입문 교육)에서는 지금까지의 내용을 다음과 같은 슬라이드로 소개합니다.

 

 

 


오늘 준비한 내용은 여기까지입니다. 정리해보면 다음과 같습니다.

  • 옵티마이져는 데이터 처리량에 따라 인데스와 Table Scan 중에 선택을 한다.
  • 옵티마이져의 선택이 완벽하지 않을 수도 있다.
  • 실제로 처리할 건수가 많아질 수록 인덱스보다는 Table Scan이 더 효과적이다.
  • 그러나 "지금도 빠르고 앞으로도 빠를것인가?" 에 대해 고민해보자.

감사합니다.


[StartUP Tuning]

  - SQL 입문을 넘어선 MySQL을 활용한 SQL 튜닝 입문 교육
  - 2024년 5월 오프라인 교육 과정을 모집중입니다.

  - https://cafe.naver.com/dbian/7717

 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

 

[StartUP SQL]

  - 데이터 분석가, 개발자, 기획자를 위한 SQL 입문 교육

  - 교육용 슬라이드 전체 무료 오픈: https://sweetquant.tistory.com/497

 

StartUP SQL 소개 및 목차

SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드 전체를 블로그에 무료 오픈했습니다. (총 409장 슬라이드, 이미지로 게시) 아래 목차를 차례대로 하나씩 따라해보시기 바랍니다. 본인의

sweetquant.tistory.com

 

 

분석대상을 로우별로 다르게 지정할 수 있는 윈도윙절입니다.

그리고 준비한 자료는 여기까지입니다. 수고하셨습니다.^^

 

 


이전 슬라이드: https://sweetquant.tistory.com/549

다음 슬라이드: 마지막입니다. 

StartUP SQL 교육 슬라이드 전체 목차로 이동

https://sweetquant.tistory.com/497

 

StartUP SQL 소개 및 목차

데이터를 강력하게 다루는 SQL! SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드를 이미지로 블로그에 무료 오픈했습니다. (총 409장의 슬라이드입니다.) 아래 목차를 차례대로 하나씩 따

sweetquant.tistory.com

 

SQL 입문을 넘어선 MySQL을 활용한 SQL 튜닝 교육 [StartUP Tuning] 오프라인 교육 과정을 모집중입니다.

https://cafe.naver.com/dbian/7717

 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

 

 

'SQL > StartUP SQL(교육슬라이드)' 카테고리의 다른 글

[StartUP SQL BOOK]SELECT 기초 - 별칭  (0) 2024.05.15
20-2. LAG와 LEAD  (0) 2024.04.11
20-1. PARTITION BY  (0) 2024.04.11
19-4. GROUP BY와 분석함수  (0) 2024.04.11
19-3. 순위 분석함수  (0) 2024.04.11
19-1~19-2. 분석함수 이해하기  (0) 2024.04.11
18. 날짜 테이블  (0) 2024.04.11
17. PIVOT  (0) 2024.04.11

다른 로우의 데이터를 현재 로우로 가져올 수 있는 LAG와 LEAD를 살펴보겠습니다.

 

 


이전 교육 슬라이드: https://sweetquant.tistory.com/548
다음 교육 슬라이드: https://sweetquant.tistory.com/550
StartUP SQL 교육 슬라이드 전체 목차: https://sweetquant.tistory.com/497

 

StartUP SQL 소개 및 목차

데이터를 강력하게 다루는 SQL! SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드를 이미지로 블로그에 무료 오픈했습니다. (총 409장의 슬라이드입니다.) 아래 목차를 차례대로 하나씩 따

sweetquant.tistory.com

 

SQL 입문을 넘어선 MySQL을 활용한 SQL 튜닝 교육 [StartUP Tuning]
2024년 5월 오프라인 교육 과정을 모집중입니다.
https://cafe.naver.com/dbian/7717

 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

 

'SQL > StartUP SQL(교육슬라이드)' 카테고리의 다른 글

[StartUP SQL BOOK]SELECT 기초 - 별칭  (0) 2024.05.15
20-3. WINDOWING  (0) 2024.04.11
20-1. PARTITION BY  (0) 2024.04.11
19-4. GROUP BY와 분석함수  (0) 2024.04.11
19-3. 순위 분석함수  (0) 2024.04.11
19-1~19-2. 분석함수 이해하기  (0) 2024.04.11
18. 날짜 테이블  (0) 2024.04.11
17. PIVOT  (0) 2024.04.11

분석함수에서 분석대상을 나눌 수 있는 PARTITION BY의 용법입니다.

'SQL > StartUP SQL(교육슬라이드)' 카테고리의 다른 글

[StartUP SQL BOOK]SELECT 기초 - 별칭  (0) 2024.05.15
20-3. WINDOWING  (0) 2024.04.11
20-2. LAG와 LEAD  (0) 2024.04.11
19-4. GROUP BY와 분석함수  (0) 2024.04.11
19-3. 순위 분석함수  (0) 2024.04.11
19-1~19-2. 분석함수 이해하기  (0) 2024.04.11
18. 날짜 테이블  (0) 2024.04.11
17. PIVOT  (0) 2024.04.11

GROUP BY와 분석함수를 혼합해서 사용하는 법을 살펴보도록 하겠습니다.

 

 


이전 교육 슬라이드: https://sweetquant.tistory.com/546
다음 교육 슬라이드: https://sweetquant.tistory.com/548

 


StartUP SQL 교육 슬라이드 전체 목차: https://sweetquant.tistory.com/497

 

StartUP SQL 소개 및 목차

데이터를 강력하게 다루는 SQL! SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드를 이미지로 블로그에 무료 오픈했습니다. (총 409장의 슬라이드입니다.) 아래 목차를 차례대로 하나씩 따

sweetquant.tistory.com


SQL 입문을 넘어선 MySQL을 활용한 SQL 튜닝 교육 [StartUP Tuning]
2024년 5월 오프라인 교육 과정을 모집중입니다.
https://cafe.naver.com/dbian/7717

 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

 

'SQL > StartUP SQL(교육슬라이드)' 카테고리의 다른 글

[StartUP SQL BOOK]SELECT 기초 - 별칭  (0) 2024.05.15
20-3. WINDOWING  (0) 2024.04.11
20-2. LAG와 LEAD  (0) 2024.04.11
20-1. PARTITION BY  (0) 2024.04.11
19-3. 순위 분석함수  (0) 2024.04.11
19-1~19-2. 분석함수 이해하기  (0) 2024.04.11
18. 날짜 테이블  (0) 2024.04.11
17. PIVOT  (0) 2024.04.11

데이터의 순위를 구하는 분석함수입니다.

 

 

 


이전 교육 슬라이드: https://sweetquant.tistory.com/545
다음 교육 슬라이드: https://sweetquant.tistory.com/547

StartUP SQL 교육 슬라이드 전체 목차: https://sweetquant.tistory.com/497

 

StartUP SQL 소개 및 목차

데이터를 강력하게 다루는 SQL! SQL을 배우기 위한 최적의 시작점 StartUP SQL! 교육 슬라이드를 이미지로 블로그에 무료 오픈했습니다. (총 409장의 슬라이드입니다.) 아래 목차를 차례대로 하나씩 따

sweetquant.tistory.com

 


SQL 입문을 넘어선 MySQL을 활용한 SQL 튜닝 교육 [StartUP Tuning]
2024년 5월 오프라인 교육 과정을 모집중입니다.
https://cafe.naver.com/dbian/7717

 

StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문

「StartUP Tuning - MySQL/MariaDB를 활용한 SQL 튜닝 입문」 < 일정 > 5/12(일), 5/19(일), 5/26(일) 오전 9시 ~ 오후 5시 (...

cafe.naver.com

 

'SQL > StartUP SQL(교육슬라이드)' 카테고리의 다른 글

20-3. WINDOWING  (0) 2024.04.11
20-2. LAG와 LEAD  (0) 2024.04.11
20-1. PARTITION BY  (0) 2024.04.11
19-4. GROUP BY와 분석함수  (0) 2024.04.11
19-1~19-2. 분석함수 이해하기  (0) 2024.04.11
18. 날짜 테이블  (0) 2024.04.11
17. PIVOT  (0) 2024.04.11
16-3. ROLLUP  (0) 2024.04.11

+ Recent posts