
HDD는 가장 대중적으로 사용되는 비휘발성 데이터 저장장치이다.
Platter라고 하는 원판에 자기를 사용하여 실제로 데이터를 읽고 쓴다.
CPU 및 시스템 보드의 소프트웨어에 의해 헤드가 플래터의 각 섹터로 이동하여 데이터를 저장한다.

HDD에 데이터를 쓸 때 파일의 크기에 따라 섹터의 일부를 사용한다. 데이터에 대한 업데이트가 발생하면 CPU는 HDD에 사용 가능한 다음 섹터에 데이터를 쓰도록 지시한다. 그 전 섹터에서 해당 새 섹터까지의 거리가 데이터를 읽는 속도에 추가되어 이러한 데이터의 분리 인스턴스가 많아질 수록 속도가 느려진다.
이러한 데이터 분리를 디스크 조각화라고 한다.
우리가 흔히 알고 있는 디스크 조각 모음을 하면 컴퓨터의 성능이 빨라진다고 하는 것이 디스크 조각화된 데이터들을 한 곳에 재정렬하는 행위이다.
HDD와 동일한 비휘발성 데이터 저장장치이다.
기존 HDD에서 플래터를 제거하고 그 대신 NAND 플래쉬 메모리와 고성능 컨트롤러를 탑재해서 HDD를 대체하고 있다.
모든 컴포넌트가 전기 장치이며 HDD와 같은 기계 장치를 가지고 있지 않다.

SSD 컨트롤러에 장착된 프로세서가 명령을 받아서 Flash 컨트롤러로 전달한다.
SSD는 자체적으로 보드에 내장된 메모리(RAM)을 가지는데 일반적으로 맵핑 정보를 저장하거나 흔히 아는 캐시 용도로 사용된다.
여러개의 Channel을 통해 서로 NAND 플래쉬 메모리 패키지로 구성된다.

성능
HDD는 직접 읽어오려는 주소의 데이터의 섹터가 도착할 때까지 기다려야 하는 Sleep 타임이 길다.
그에 반해 SSD는 전기 신호로 해결하기 때문에 데이터를 쓰고 읽는 속도가 월등히 빠르다.
HDD가 데이터 센터에 직접 걸어가서 필요한 자료를 찾아 집에 오는 방식이라면, SSD는 데이터 센터에 전화를 걸어 확인하는 방식이라고 이해하면 쉽다.
데이터 보존력
SSD는 데이터 휘발성이 HDD에 비해 높다.
플래쉬 메모리는 정전기에 취약하고 데이터가 자연 증발하기도 한다.
HDD는 손상되어도 자기 기록의 흔적이 남아있으면 일부라도 복구가 가능하지만, SSD는 데이터 정보가 증발하면 말 그대로 흔적 없이 소멸된다.
가격 대비 용량
HDD가 SSD에 비해 가격 대비 용량이 월등히 높다. (약 4배)
Database는 Data를 Block 단위로 읽고 저장한다.
대부분의 데이터베이스는 8kb가 적합, Oracle도 기본 사이즈가 8kb
데이터베이스 튜닝에서 중요한 것이
>> 블록 단위의 I/O 줄이기

OS 또는 I/O 서브 시스템이 I/O를 처리하는 동안 프로세스는 잠을 잔다. (Waiting)
생성 이후 종료 전까지 준비와 실행과 대기 상태를 반복한다.
여러 프로세스가 하나의 CPU를 공유할 수 있지만, 특정 순간에는 하나의 프로세스만 CPU를 사용할 수 있기 때문에 이런 메커니즘이 필요하다.
Interrupt 없이 일하던 프로세스도 디스크에서 데이터를 읽어야 할 때는 CPU를 OS에 반환하고 잠시 Waiting 상태에서 I/O가 완료되기를 기다린다.
Random I/O
데이터를 임의의 위치에서 읽거나 쓰는 작업
Sequential I/O
데이터를 연속적인 블록으로 순차적으로 읽거나 쓰는 작업
HDD에서 여러개의 데이터를 입력할 때 순차 I/O는 헤더를 한 번만 움직이지만, 랜덤 I/O는 데이터의 개수 만큼 움직여야 한다.
디스크의 헤더를 움직이는 시간이 데이터를 쓰고 읽는 데 걸리는 시간에서 가장 많은 부분을 차지하는 병목이 되는 지점
SSD는 기계적 장치를 사용하지 않고 전기적 신호를 통해 데이터를 읽고 쓰기 때문에 그럼 상관없겠네?
라고 생각할 수 있지만, SSD에서도 랜덤 I/O는 순차 I/O보다 Throughput이 떨어진다.
위에서 언급한 쿼리의 튜닝은 그냥 I/O 보다는 랜덤 I/O를 줄이는 것이 목적이라고 할 수 있다.
SQL을 수행하는 과정에서 계속해서 데이터 블록을 읽게 되는데 자주 읽는 블록을 매번 디스크에서 읽어 오는 것은 비효율적이다.
>> 모든 DBMS에 데이터 캐싱 메커니즘이 필수인 이유

서버 프로세스와 데이터 파일 사이에 존재해서 데이터 블록을 읽을 땐 항상 버퍼 캐시부터 탐색한다.
공유되는 메모리 영역이기 때문에 같은 블록을 읽어야 하는 다른 프로세스도 이득을 보는 경우가 있다.
Memory I/O
메인 메모리(RAM)에서 데이터를 읽고 쓰는 작업
디스크에서 한 번 읽힌 데이터는 버퍼 캐시에 적재됨
이후 동일한 데이터를 다시 사용할 때는 디스크가 아닌 메모리에서 즉시 접근
디스크 I/O에 비해서 월등하게 빠름
Disk I/O
디스크(HDD / SSD)에서 데이터를 읽고 쓰는 작업
DB 파일, 테이블, 인덱스 등은 기본적으로 디스크에 저장
사용자가 쿼리를 실행하면 해당 데이터를 디스크에서 메모리로 불러오는 과정이 발생
결론적으로 DB 성능 최적화를 위해서 디스크 I/O를 줄여야 함
Logical I/O
메모리(버퍼 캐시)에서 데이터 페이지를 읽는 작업
디스크에서 이미 읽혀져 메모리에 올라와있는 페이지를 접근하는 것
인덱스 탐색, 버퍼 풀 조회
Physical I/O
디스크에서 데이터 페이지를 직접 읽는 작업
버퍼 풀에 데이터가 없을 때
위에서도 언급했듯이 I/O 튜닝의 핵심은 I/O 요청 횟수를 최소화 하는 데에 있다.
디스크 접근을 줄이고 메모리에 있는 데이터를 최대환 활용해서 처리해야 한다.
SQL 최적화
인덱스를 사용 가능하도록 범위 조건, 비교 연산, 등호 연산 등을 명확히 작성
LIKE ‘%값%’ 등 Prefix가 없는 조건은 인덱스 미사용 → Full Scan 유발
옵티마이저가 최적 경로를 선택할 수 있게 정보 제공
통계 정보 최신화
Full Table Scan 방지를 위한 힌트
SELECT (Column) : 작성순서 (1), 실행순서 (5)
FROM (Table) : 작성순서 (2), 실행순서 (1)
WHERE (Table Condition) : 작성순서 (3), 실행순서 (2)
GROUP BY (Column) : 작성순서 (4), 실행순서 (3)
HAVING (Group Condtion) : 작성순서 (5), 실행순서 (4)
ORDER BY (Column) : 작성순서 (6), 실행순서 (6)
실행 순서에 따른 설명

쿼리의 실행 절차 중 parse tree를 기반으로 실행 계획을 세우는 역할을 한다.
자체적인 동작 순서
종류
비용 기반 최적화, CBO(Cost-Based Optimizer)
쿼리를 처리하기 위한 여러 가능한 방법을 만듦
각 단위 작업의 비용(부하) 정보와 대상 테이블의 예측된 통계 정보를 이용해 실행 계획별 비용을 산출
이렇게 산출된 실행 방법 별로 비용이 최소로 소요되는 처리 방식을 선택해 최종적으로 쿼리를 실행
규칙 기반 최적화, RBO(Rule-Based Optimizer)
기본적으로 대상 테이블의 레코드 건수나 선택도 등을 고려하지 않음
옵티마이저에 내장된 우선 순위에 따라 실행 계획 수립
통계 정보를 조사하지 않기 때문에 같은 쿼리에 대해서는 거의 항상 같은 실행 방법

Table Full Scan
Sequenctial access와 Multiblock I/O 방식으로 디스크 블록을 읽는다.
MySQL 옵티마이저는 다음과 같은 조건일 때 선택
Index Range Scan
Randomly access와 Single Bloc I/O 방식으로 디스크 블록을 읽는다.
병렬, ORDER BY(Index, filesort), GROUP BY, DISTINCT, 내부 임시 테이블, 스위치 옵션, 조인 등의 쿼리 최적화 관련은 후 주차에 정리할 내용이라 그 때 정리할 예정이다.
그래서 Optimzer가 실행 계획을 세운다는 건 알겠는데, 그 근거가 뭔데?
SQL 서버는 쿼리를 최적화 하기 위해 통계를 사용한다.
이 통계는 데이터 분포에 대한 정보를 SQL 서버에 제공하여 효율적인 실행 계획을 생성을 돕는다.
통계는 특히 Index가 있는 컬럼이나 WHERE 절에서 자주 사용되는 컬럼에서 중요한 역할을 한다.
잘못된 통계는 부적절한 실행 계획을 생성할 수 있고 성능 저하를 야기할 수 있다.
SQL 서버의 통계는 특정 컬럼에 대한 데이터 분포를 나타낸다.
이를 통해 쿼리 최적화 도구는 쿼리 실행 시 가장 효율적인 접근 방식을 선택할 수 있다.
통계는 주로 히스토그램과 밀도 정보로 구성됩니다.
통계는 주로 다음 두 가지 방식으로 생성
예시
만약 통계가 부정확하거나 최신화되지 않은 경우