데이터베이스 테이블에서 데이터를 찾는 방법은 무엇이 있을까?

  • 테이블 전체를 스캔한다.
  • 인덱스를 이용한다.

위 두 가지 방법이 있다. 

 

테이블 전체 스캔과 관련해서는 튜닝 요소가 많지 않지만, 인덱스와 관련해서는 튜닝 요소가 매우 많고 기법도 다양하여 SQL을 공부할때 가장 먼저 다루어야 한다.

 

인덱스 튜닝의 두 가지 핵심요소

인덱스는 큰 테이블에서 소량 데이터를 검색할때 사용한다. 여러 가지 방법이 있지만, 핵심요소는 크게 두 가지로 나뉜다. 

 

첫 번째는 인덱스 스캔 과정에서 발생하는 비효율을 줄이는 것이다. 즉, 인덱스 스캔 효율화 튜닝이다.

 

인덱스 튜닝의 두 번째 핵심요소는 테이블 엑세스 횟수를 줄이는 것이다. 인덱스 스캔 후 테이블 레코드를 액세스할 때 랜덤 I/O 방식을 사용하므로 이를 랜덤 액세스 최소화 튜닝이라고 한다.                                                                                                                                                                                                                                                                                                    

인덱스 스캔 효율화 튜닝과 랜덤 액세스 튜닝 둘 다 중요하지만, 더 중요한 하나를 고른다면 랜덤 액세스 최소화 튜닝이다. 성능에 미치는 여향이 더 크기 때문이다.

 

SQL 튜닝은 랜덤 I/O와의 전쟁

데이터베이스 성능이 느린 이유는 디스크 I/O 때문이다. 읽어야 할 데이터량이 많고, 그 과정에서 디스크 I/O가 많이 발생할 때 느리다.

 

인덱스의 구조에 대해서 알아보자

 

인덱스 구조

인덱스는 대용량 테이블에서 필요한 데이터만 빠르게 효율적으로 액세스하기 위해 사용하는 오브젝트다. 모든 책 뒤쪽에 있는 색인과 같은 역할을 한다.

데이터베이스에서 인덱스 없이 데이터를 검색하려면, 테이블을 처음부터 끝까지 모두 읽어야 한다. 반면, 인덱스를 이용하면 일부만 읽고 멈출 수 있다. 즉, 범위 스캔(Range Scan이 가능하다. 범위 스캔이 가능한 이유는 인덱스가 정렬돼 있기 때문이다.

 

DBMS는 일반적으로 B*Tree 인덱스를 사용한다. 

나무(Tree)를 거꾸로 뒤집은 모양이여서 뿌리(Root)가 위쪽에 있고, 가지(Branch)를 거쳐 맨 아래에 잎사귀(Leaf)가 있다.

 

인덱스의 탐색 과정은 수직적 탐색과 수평적 탐색으로 나눌 수 있다.

  • 수직적 탐색 : 인덱스 스캔 시작지점을 찾는 과정
  • 수평적 탐색 : 데이터를 찾는 과정

 

 

                                                                       

'Back-End > DB' 카테고리의 다른 글

SQL 파싱과 최적화  (3) 2024.07.25
Lock 과 트랜잭션 동시성 제어 (Oracle)  (3) 2024.07.23
인덱스의 기본 (2)  (0) 2023.10.12
인덱스를 사용하는 이유  (0) 2023.09.14
DB 설계를 잘못하면 생기는 일  (1) 2023.09.13
  • 스프링은 프레임워크다.
  • 스프링은 오픈소스다.
  • 스프링은 IOC 컨테이너를 가진다.
  • 스프링은 DI를 지원한다.
  • 스프링은 엄청나게 많은 필터를 가지고 있다.
  • 스프링은 MessageContertor를  가지고 있다. 기본값은 현재 Json이다.
  • 스프링은 BufferedReader 와 BufferedWriter를 쉽게 사용가능하다.\

 

스프링은 프레임워크다

framework 를 살펴보면 frame : 틀 + work : 동작하다 이다. 

풀이를 해보면 어떤 틀에서 동작하는 것이다. 틀을 제공해주고 여기에 맞춰서 개발을 하면 누구나 좋은 프로그램을 만들 수 있기 때문에 사용한다.

 

 

IOC(Inversion Of Controll)

뜻을 해석해 보면 역전의 제어이다 즉 주도권이 스프링에게 있다는 것이다.

 

우선 class, object, instance 에 대해 알아야 한다.

  • class : 설계도
  • object : 실체화가 가능한 어떤 것
  • instance : 실체과 된 것

만약 가구가 있다고 해보자 가구는 추상적이다. 가구에 해당하는 의자, 침대, 책상이 있다고 하면 의자, 침대, 책상은 object에 해당한다. 이 object들이 실체화가 되면 그게 instance가 되는 것이다.

 

그렇다면 IOC 는 무엇일까? 

만약 오브젝트를 만들어 본다고 하면 

 

의자 chair = new 의자();

위의 chair 는 힙 메모리에 저장되어 사용 가능하게 된다. IOC는 이러한 수많은 object 들을 읽어서 직접 사용가능하게 해주는 것이다.

 

 

DI(Dependencies Injection)

위 단어를 해석해 보면 의존성 주입이라는 뜻이다. 

스프링이 내가 만든 class 들을 관리하는데 내가 원하는 다른 곳에서 사용(공유)할 수 있게 해주는 것이 DI이다.

위에 있는 IOC와 연관이 되어 있다.

 

'Back-End > Java' 카테고리의 다른 글

스레드  (1) 2024.07.05
프로세스  (0) 2024.07.04
Java HTTP 통신  (4) 2024.06.12
Exception과 Transaction  (1) 2024.02.05
String, StringBuilder, StringBuffer 의 차이점  (1) 2023.10.26

인덱스를 사용하는 이유에 대해서 생각해보자 왜 사용할까?

  • 조건을 만족하는 듀플(들)을 빠르게 조회하기 위해서
  • 빠르게 정렬하거나 그룹핑 하기 위해서

사용한다고 볼 수 있다. 한마디로 정의하자면 

특정 조건을 만족하는 데이터를 빠르게 찾기 위해 인덱스를 사용한다고 보면 된다.

 

MySql 기준으로 인덱스를 생성하려면

 

CREATE INDEX 인덱스명 ON 테이블명;

CREATE INDEX 인덱스명 ON 테이블명(컬럼명);

 

중복을 허용하지 않는 UNIQUE INDEX

 

CREATE UNIQUE INDEX  인덱스명 ON 테이블명(컬럼명1, 컬럼명2);

 , 를 사용하여 여러 필드에 인덱스를 설정해 줄 수 있다. 

 

인덱스는 대부분의 DBMS에서 프라이머리 키로 설정하면 자동으로 생성해준다.

 

인덱스를 확인하려면

 

SHOW INDEX FROM 테이블명; 

쿼리를 사요하면 된다.

 

SELECT 쿼리에서 내가 원하는 인덱스를 사용하고 싶으면 

SELECT * FROM 테이블명 INDEX (인덱스명) WHERE 조건절;

 

인덱스를 사용하면 조회시간을 단축할 수 있다. 그러면 최대한 많으면 많을수록 좋은게 아닐까?

그럴것 같지만 아니다.

 

인덱스를 생성할때마다 인덱스를 저장하는 부가적인 데이터가 생성되고, 테이블에 write (수정,삽입,삭제) 가 빈번하다면 인덱스도 동일하게 write 해줘야 하기 때문에 부하가 발생할 수 있고 저장공간의 낭비가 생길 수 있다.

그렇기 때문에 불필요한 인덱스는 만들지 말아야한다.

 

또 Full Scan 방식이 더 좋은 경우도 있다.

  • table에 데이터가 별로 없는 경우 (수십~수백건)
  • 조회하려는 데이터가 테이블의 상당 부분을 차지할때

 

 

 

 

'Back-End > DB' 카테고리의 다른 글

SQL 파싱과 최적화  (3) 2024.07.25
Lock 과 트랜잭션 동시성 제어 (Oracle)  (3) 2024.07.23
인덱스의 기본 (2)  (0) 2023.10.12
인덱스의 기본  (3) 2023.10.11
DB 설계를 잘못하면 생기는 일  (1) 2023.09.13

데이터베이스 스키마 설계를 잘못하면 어떤 일이 발생할까?

empt_id empi_name birth_date position salary dept_id dept_name
1 D 1995 null 10000 1001  DEV

위 와 같은 테이블이 있다고 가정을 해보자 임직원의 정보와 해당 임직원의 부서 정보를 모두 같이 가지고 있는 테이블 구조이다.

그렇다면 위와 같이 테이블을 설계했다면 발생하게 되는  일을 생각해보자

 

직원이 한명 입사하여 새로운 임직원의 정보를 등록해보자

empt_id empi_name birth_date position salary dept_id dept_name
1 D 1995 null 10000 1001  DEV
2 Simon 1999 null 3000 1001 DEV

부서 아이디와 부서 명이 중복된 데이터가 생기게 된다. 이렇게 되면 저장 공간의 낭비가 발생하게되고, 실수로 인한 데이터 불일치 가능성이 존재하게된다. (부서명을 실수로 DEB로 입력한다면 같은 부서이지만 부서명이 다르게 된다.)

 

이번에는 부서의 배치를 받지 못한 임직원이 입사를 했다고 생각해보자

empt_id empi_name birth_date position salary dept_id dept_name
1 D 1995 null 10000 1001  DEV
2 Simon 1999 null 3000 1001 DEV
3 Jen 2000 null null null null

Jen 의 부서정보는 모두 null 데이터가 들어가게 된다. 할 수 있다면 null 값은 최대한 적에 사용하는것이 좋다.

 

이번에는 새로운 부서가 창설되었다고 생각해보자

empt_id empi_name birth_date position salary dept_id dept_name
1 D 1995 null 10000 1001  DEV
2 Simon 1999 null 3000 1001 DEV
3 null null null null 1002 QA

QA 부서 저장 용 row를 생성해야 하는데 위 예시와 같이 매끄럽지도 않고 null 데이터도 많이 들어가게 된다. (empt_id 는 primary key 이기 때문에 임시 값이 들어갔다.)

 

이렇게 만들어진 부서에 임직원이 최초로 들어왔다고 생각해보자

empt_id empi_name birth_date position salary dept_id dept_name
1 D 1995 null 10000 1001  DEV
2 Simon 1999 null 3000 1001 DEV
3 null null null null 1002 QA
4 Ujon 2001 null 1500 1002 QA

그렇다면 위에 empt_id = 3 에 해당하는 정보는 더 이상 필요 없게 된다.

 

 

위 테이블을 정상적으로 구분하여 만들어보자

empt_id empt_name birth_date position salary
1 D 1995 null 10000
2 Simon 1999 null 3000
3 Ujon 2001 null 1500
dept_id dept_name
1001 DEV
1002 QA

위와 같이 2개의 테이블로 나눠 데이터를 저장하게 되면 해결될 것이다.

'Back-End > DB' 카테고리의 다른 글

SQL 파싱과 최적화  (3) 2024.07.25
Lock 과 트랜잭션 동시성 제어 (Oracle)  (3) 2024.07.23
인덱스의 기본 (2)  (0) 2023.10.12
인덱스의 기본  (3) 2023.10.11
인덱스를 사용하는 이유  (0) 2023.09.14

+ Recent posts