본문 바로가기

혼자공부하는 SQL

6. 인덱스-3

0. 학습 목표

  • 인덱스의 개념과 종류를 이해
  • 인덱스의 작동 원리와 구조를 이해
  • 실제로 인덱스를 만들고 사용하는 방법을 학습

0. 요약

  • 인덱스는 내부적으로 균형트리로 구성된
  • 노드는 트리 구조에서 데이터가 저장되는 공간인데 MySQL에서는 노드를 페이지라고 부름
  • 전체 테이블 검색은 데이터를 처음부터 끝가지 검색
  • 페이지 분할은 데이터를 입력할 때 입력할 페이지 공간이 없어 2개 페이지로 데이터가 나눠지는 것을 의미
  • 인덱스 검색은 클러스터형/보조 인덱스를 이용해서 데이터를 검색, 속도 빠름
  • CREATE INDEX 문으로 인덱스를 생성할 수 있음
  • 기본 / 고유 키로 자동 생성된 인덱스는 ALTER TABLE로 제거하고 CREATE INDEX로 생성한 인덱스는 DROP INDEX문으로 제거
  • 단순 보조 인덱스는 중복을 허용하는 보조 인덱스로 CREATE INDEX문을 사용
  • 고유 보조 인덱스는 중복을 허용하지 않는 보조 인덱스로 CREATE UNIQUE INDEX문을 사용
  • MySQL 워크벤치에서 SQL을 실행한 후 실행 계획에서 인덱스의사용 여부를 확인할 수 있음

3. 인덱스의 실제 사용

※핵심 키워드:  CREATE INDEX, DROP INDEX, 단순 보조 인덱스, 고유 보조 인덱스, 실행 계획

단순 보조 인덱스 및 고유 보조 인덱스를 생성하고 제거하는 방법을 익히고, MySQL의 실행 계획(Execution Plan)에서 인덱스를 효율적으로 사용하는 방법을 알아보자.

인덱스를 생성하는 SQL을 익혀보자. 인덱스 생성/제거하는 기본 형식은 아래와 같다.

CREATE [UNIQUE] INDEX 인덱스_이름
	ON 테이블_이름 (열_이름) [ASC | DESC]
DROP INDEX 인덱스_이름 ON 테이블_이름

3-1. 인덱스생성과 제거 문법

인덱스 생성 문법

테이블을 생성할 때 특정 열을 기본 키, 고유 키로 생성하면 인덱스가 자동 생성 된다. PRIMARY KEY는 클러스터형, UNIQUE는 보조형 인덱스가 자동으로 생성된다.

그 외에 직접 인덱스를 생성하려면 CREATE INDEX문을 사용한다. 

CREATE [UNIQUE] INDEX 인덱스_이름
	ON 테이블_이름 (열_이름) [ASC | DESC]

상세 설명은 다음과 같다.

  • UNIQUE는 중복이 안 되는 고유 인덱스를 만드는 것, 생략하면 중복 가능, 기존에 중복된 값이 있으면 UNIQUE로 생성 불가능
  • ASC | DESC는 오름/내림 차순 지정, 기본은 오름 차순이며 내림 차순을 사용할 일은 거의 없음

인덱스 제거 문법

CREATE INDEX로 생성한 인덱스는 DROP INDEX로 제거 가능하다. 

DROP INDEX 인덱스_이름 ON 테이블_이름

다만 기본 키, 고유 키로 자동 생성된 인덱스는 DROP INDEX로 삭제할 수 없다. 당연히 ALTER TABLE 문으로 기본 키나 고유키를 제거 후에는 삭제 가능하다.

참고로 클러스터형, 보조형 인덱스를 삭제하는 경우는 보조형 -> 클러스터형 순으로 삭제하는 것이 좋다. 클러스터형 부터 삭제하면 데이터가 재구성 되기 때문이다


3-2. 인덱스생성과 제거 실습

인덱스 생성 실습

인덱스 실습을 위해 인터넷 마켓 데이터베이스를 생성하자.

DROP DATABASE IF EXISTS market_db; -- 만약 market_db가 존재하면 우선 삭제한다.
CREATE DATABASE market_db;

USE market_db;
CREATE TABLE member -- 회원 테이블
( mem_id  		CHAR(8) NOT NULL PRIMARY KEY, -- 사용자 아이디(PK)
  mem_name    	VARCHAR(10) NOT NULL, -- 이름
  mem_number    INT NOT NULL,  -- 인원수
  addr	  		CHAR(2) NOT NULL, -- 지역(경기,서울,경남 식으로 2글자만입력)
  phone1		CHAR(3), -- 연락처의 국번(02, 031, 055 등)
  phone2		CHAR(8), -- 연락처의 나머지 전화번호(하이픈제외)
  height    	SMALLINT,  -- 평균 키
  debut_date	DATE  -- 데뷔 일자
);
CREATE TABLE buy -- 구매 테이블
(  num 		INT AUTO_INCREMENT NOT NULL PRIMARY KEY, -- 순번(PK)
   mem_id  	CHAR(8) NOT NULL, -- 아이디(FK)
   prod_name 	CHAR(6) NOT NULL, --  제품이름
   group_name 	CHAR(4)  , -- 분류
   price     	INT  NOT NULL, -- 가격
   amount    	SMALLINT  NOT NULL, -- 수량
   FOREIGN KEY (mem_id) REFERENCES member(mem_id)
);

INSERT INTO member VALUES('TWC', '트와이스', 9, '서울', '02', '11111111', 167, '2015.10.19');
INSERT INTO member VALUES('BLK', '블랙핑크', 4, '경남', '055', '22222222', 163, '2016.08.08');
INSERT INTO member VALUES('WMN', '여자친구', 6, '경기', '031', '33333333', 166, '2015.01.15');
INSERT INTO member VALUES('OMY', '오마이걸', 7, '서울', NULL, NULL, 160, '2015.04.21');
INSERT INTO member VALUES('GRL', '소녀시대', 8, '서울', '02', '44444444', 168, '2007.08.02');
INSERT INTO member VALUES('ITZ', '잇지', 5, '경남', NULL, NULL, 167, '2019.02.12');
INSERT INTO member VALUES('RED', '레드벨벳', 4, '경북', '054', '55555555', 161, '2014.08.01');
INSERT INTO member VALUES('APN', '에이핑크', 6, '경기', '031', '77777777', 164, '2011.02.10');
INSERT INTO member VALUES('SPC', '우주소녀', 13, '서울', '02', '88888888', 162, '2016.02.25');
INSERT INTO member VALUES('MMU', '마마무', 4, '전남', '061', '99999999', 165, '2014.06.19');

INSERT INTO buy VALUES(NULL, 'BLK', '지갑', NULL, 30, 2);
INSERT INTO buy VALUES(NULL, 'BLK', '맥북프로', '디지털', 1000, 1);
INSERT INTO buy VALUES(NULL, 'APN', '아이폰', '디지털', 200, 1);
INSERT INTO buy VALUES(NULL, 'MMU', '아이폰', '디지털', 200, 5);
INSERT INTO buy VALUES(NULL, 'BLK', '청바지', '패션', 50, 3);
INSERT INTO buy VALUES(NULL, 'MMU', '에어팟', '디지털', 80, 10);
INSERT INTO buy VALUES(NULL, 'GRL', '혼공SQL', '서적', 15, 5);
INSERT INTO buy VALUES(NULL, 'APN', '혼공SQL', '서적', 15, 2);
INSERT INTO buy VALUES(NULL, 'APN', '청바지', '패션', 50, 1);
INSERT INTO buy VALUES(NULL, 'MMU', '지갑', NULL, 30, 1);
INSERT INTO buy VALUES(NULL, 'APN', '혼공SQL', '서적', 15, 1);
INSERT INTO buy VALUES(NULL, 'MMU', '지갑', NULL, 30, 4);

SELECT * FROM member;

# mem_id, mem_name, mem_number, addr, phone1, phone2, height, debut_date
'APN', '에이핑크', '6', '경기', '031', '77777777', '164', '2011-02-10'
'BLK', '블랙핑크', '4', '경남', '055', '22222222', '163', '2016-08-08'
'GRL', '소녀시대', '8', '서울', '02', '44444444', '168', '2007-08-02'
'ITZ', '잇지', '5', '경남', NULL, NULL, '167', '2019-02-12'
'MMU', '마마무', '4', '전남', '061', '99999999', '165', '2014-06-19'
'OMY', '오마이걸', '7', '서울', NULL, NULL, '160', '2015-04-21'
'RED', '레드벨벳', '4', '경북', '054', '55555555', '161', '2014-08-01'
'SPC', '우주소녀', '13', '서울', '02', '88888888', '162', '2016-02-25'
'TWC', '트와이스', '9', '서울', '02', '11111111', '167', '2015-10-19'
'WMN', '여자친구', '6', '경기', '031', '33333333', '166', '2015-01-15'

SHOW INDEX 문으로 member 테이블에 어떤 인덱스가 설정되어 있는지 확인하자.

SHOW INDEX FROM member;

# Table, Non_unique, Key_name, Seq_in_index, Column_name, Collation, Cardinality, Sub_part, Packed, Null, Index_type, Comment, Index_comment, Visible, Expression
'member', '0', 'PRIMARY', '1', 'mem_id', 'A', '2', NULL, NULL, '', 'BTREE', '', '', 'YES', NULL
  • key_name이 PRIMARY로 클러스터형 인덱스
  • mem_id에 클러스터형 인덱스가 설정
  • Non_unique가 0이므로 고유한 값

이번에는 인덱스 크기를 확인하자.

SHOW TABLE STATUS LIKE 'member';

# Name, Engine, Version, Row_format, Rows, Avg_row_length, Data_length, Max_data_length, Index_length, Data_free, Auto_increment, Create_time, Update_time, Check_time, Collation, Checksum, Create_options, Comment
'member', 'InnoDB', '10', 'Dynamic', '10', '1638', '16384', '0', '0', '0', NULL, '2022-02-14 19:33:45', '2022-02-14 19:33:45', NULL, 'utf8mb4_0900_ai_ci', NULL, '', ''

우선 LIKE를 쓴 것은 member라는 글자가 들어간 테이블의 정보를 보는 것인데 여기서는 member가 들어간 테이블은 1개밖에 없으므로 member 테이블의 정보를 확인한 것이다.

위에서 알 수 있는 정보는 Data_length는 클러스터형 인덱스 크기를 byte로 표시한 것이다. 즉 16KB이다. Index_length는 보조형 인덱스의 크기인데 없기 때문에 0이다.

이번에는 addr에 중복을 허용하는 단순 보조 인덱스를 생성하자.

CREATE INDEX idx_member_addr
	ON member (addr);

인덱스 정보를 살펴보자.,

SHOW INDEX FROM member;

# Table, Non_unique, Key_name, Seq_in_index, Column_name, Collation, Cardinality, Sub_part, Packed, Null, Index_type, Comment, Index_comment, Visible, Expression
'member', '0', 'PRIMARY', '1', 'mem_id', 'A', '2', NULL, NULL, '', 'BTREE', '', '', 'YES', NULL
'member', '1', 'idx_member_addr', '1', 'addr', 'A', '5', NULL, NULL, '', 'BTREE', '', '', 'YES', NULL
  • Non_unique가 0이므로 중복 데이터를 허용
  • Key_name은 idx_member_addr
  • Column_name은 설정한 addr

다시 인덱스의 크기를 확인하자.

SHOW TABLE STATUS LIKE 'member';

# Name, Engine, Version, Row_format, Rows, Avg_row_length, Data_length, Max_data_length, Index_length, Data_free, Auto_increment, Create_time, Update_time, Check_time, Collation, Checksum, Create_options, Comment
'member', 'InnoDB', '10', 'Dynamic', '10', '1638', '16384', '0', '0', '0', NULL, '2022-02-14 19:41:39', '2022-02-14 19:33:45', NULL, 'utf8mb4_0900_ai_ci', NULL, '', ''

Index_length가 0인 것이 확인된다. 이유는 생성한 인덱스를 실제로 적용시키려면 ANALYZE TABLE문으로 먼저 테이블을 분석 처리해 줘야하기 때문이다.

ANALYZE TABLE member;
SHOW TABLE STATUS LIKE 'member';

# Name, Engine, Version, Row_format, Rows, Avg_row_length, Data_length, Max_data_length, Index_length, Data_free, Auto_increment, Create_time, Update_time, Check_time, Collation, Checksum, Create_options, Comment
'member', 'InnoDB', '10', 'Dynamic', '10', '1638', '16384', '0', '16384', '0', NULL, '2022-02-14 19:41:39', '2022-02-14 19:33:45', NULL, 'utf8mb4_0900_ai_ci', NULL, '', ''

이제 index_length가 정상적으로 생성된 것이 확인된다.

이번에는 mem_number에 중복을 허용하지 않는 고유 보조 인덱스를 생성해보자. 중복된 값이 있기 때문에 실패한다.

CREATE UNIQUE INDEX idx_member_mem_number
	ON member (mem_number);
    
19:50:38	CREATE UNIQUE INDEX idx_member_mem_number  ON member (mem_number)	Error Code: 1062. Duplicate entry '4' for key 'member.idx_member_mem_number'	0.015 sec

mem_name은 중복된 값이 없으므로 생성할 수 있다.

CREATE UNIQUE INDEX idx_member_mem_name
	ON member (mem_name);

SHOW INDEX FROM member;

# Table, Non_unique, Key_name, Seq_in_index, Column_name, Collation, Cardinality, Sub_part, Packed, Null, Index_type, Comment, Index_comment, Visible, Expression
'member', '0', 'PRIMARY', '1', 'mem_id', 'A', '10', NULL, NULL, '', 'BTREE', '', '', 'YES', NULL
'member', '0', 'idx_member_mem_name', '1', 'mem_name', 'A', '10', NULL, NULL, '', 'BTREE', '', '', 'YES', NULL
'member', '1', 'idx_member_addr', '1', 'addr', 'A', '5', NULL, NULL, '', 'BTREE', '', '', 'YES', NULL

그럼 mem_name이 "마마무"이고 mem_id가 "MOO"인 값을 입력하면 어떻게 될까?, 즉 mem_id는 기본 키로 중복되면 안되는 값이므로 변경하여 넣고 이름은 인덱스만 중복되지 않도록 설정하였을 때 가능한지 확인하는 건이다. 결론적으로는 인덱스에 중복된 값을 허용하지 않았으므로 입력되지 않는다.

INSERT INTO member VALUES('MOO', '마마무', 2, '태국', '001', '12341234', 155, '2020.10.10');

19:55:45	INSERT INTO member VALUES('MOO', '마마무', 2, '태국', '001', '12341234', 155, '2020.10.10')	Error Code: 1062. Duplicate entry '마마무' for key 'member.idx_member_mem_name'	0.015 sec

이처럼 고유 보조 인덱스를 설정하는 경우는 주민번호, 학번, 이메일등 중복될 수 없는 값이 설정해야 한다.

추가적으로 중복된 데이터가 많은 열에는 인데스를 생성하지 않는 것이 좋다. 예를 들어 남성은 M, 여성은 F로 설정하였을 때 회원이 100만명이면 50만명씩 위 값을 나눠 가질 것이다. 이것은 쓸데없는 인덱스로 검색 조건 및 성능에 악영향을 줄 수 있다.


인덱스의 활용 실습

인덱스를 통해서 결과를 출력하고 인덱스가 없으면 전체 테이블을 찾아서 결과를 출력했다. 인덱스를 이해하지 못하면 빠른 결과를 내야 할 때 제대로 활용하지 못할 수 있다.

먼저 지금까지 만든 인덱스가 어느 열에 있는지 확인해 보자.

  • mem_id: PRIMARY KEY(클러스터형 인덱스)
  • mem_name: 보조형 인덱스(UNIQUE)
  • addr: 보조형 인덱스
USE market_db;
ANALYZE TABLE member;
SHOW INDEX FROM member;

# Table, Non_unique, Key_name, Seq_in_index, Column_name, Collation, Cardinality, Sub_part, Packed, Null, Index_type, Comment, Index_comment, Visible, Expression
'member', '0', 'PRIMARY', '1', 'mem_id', 'A', '10', NULL, NULL, '', 'BTREE', '', '', 'YES', NULL
'member', '0', 'idx_member_mem_name', '1', 'mem_name', 'A', '10', NULL, NULL, '', 'BTREE', '', '', 'YES', NULL
'member', '1', 'idx_member_addr', '1', 'addr', 'A', '5', NULL, NULL, '', 'BTREE', '', '', 'YES', NULL

이번에는 전체를 조회해 보자. 하지만 이 SQL문은 인덱스와 아무 상관 없다. 인덱스를 사용하려면 인덱스가 생성된 열 이름이 SQL문에 있어야 한다.

SELECT * FROM member;

# mem_id, mem_name, mem_number, addr, phone1, phone2, height, debut_date
'APN', '에이핑크', '6', '경기', '031', '77777777', '164', '2011-02-10'
'BLK', '블랙핑크', '4', '경남', '055', '22222222', '163', '2016-08-08'
'GRL', '소녀시대', '8', '서울', '02', '44444444', '168', '2007-08-02'
'ITZ', '잇지', '5', '경남', NULL, NULL, '167', '2019-02-12'
'MMU', '마마무', '4', '전남', '061', '99999999', '165', '2014-06-19'
'OMY', '오마이걸', '7', '서울', NULL, NULL, '160', '2015-04-21'
'RED', '레드벨벳', '4', '경북', '054', '55555555', '161', '2014-08-01'
'SPC', '우주소녀', '13', '서울', '02', '88888888', '162', '2016-02-25'
'TWC', '트와이스', '9', '서울', '02', '11111111', '167', '2015-10-19'
'WMN', '여자친구', '6', '경기', '031', '33333333', '166', '2015-01-15'

인덱스를 사용했는지 여부는 [Execution Plan]창을 확인해보면 된다.

보는 봐와 같이 Full Table Scan으로 전체 테이블을 스캔한 결과이다.

이번에는 인덱스가 있는 열을 조회해 보자.

SELECT mem_id, mem_name, addr FROM member;

# mem_id, mem_name, addr
'APN', '에이핑크', '경기'
'BLK', '블랙핑크', '경남'
'GRL', '소녀시대', '서울'
'ITZ', '잇지', '경남'
'MMU', '마마무', '전남'
'OMY', '오마이걸', '서울'
'RED', '레드벨벳', '경북'
'SPC', '우주소녀', '서울'
'TWC', '트와이스', '서울'
'WMN', '여자친구', '경기'

인덱스를 사용했는지 [Execution Plan]창을 확인해 보자.

역시 이번에도 인덱스를 사용하지 않았다.

이번에는 인덱스가 생성된 mem_name 값이 "에이핑크"인 행을 조회해 보자. 이것은 인덱스를 사용해서 결과를 얻는다.

SELECT mem_id, mem_name, addr FROM member WHERE mem_name = '에이핑크';

# mem_id, mem_name, addr
'APN', '에이핑크', '경기'

 

이번에는 숫자의 범위로 조회해 보자. 먼저 숫자로 구성된 인원수(mem_number)로 단순 보조 인덱스를 만들자.

CREATE INDEX idx_member_mem_number
	ON member(mem_number);
ANALYZE TABLE member;

인원수가 7명 이상인 그룹의 이름과 인원수를 조회해 보자.

SELECT mem_id, mem_name, addr FROM member WHERE mem_number >= 7;

# mem_id, mem_name, addr
'GRL', '소녀시대', '서울'
'OMY', '오마이걸', '서울'
'SPC', '우주소녀', '서울'
'TWC', '트와이스', '서울'

확인해 보면 Index Range Scan으로 숫자의 범위로 조회하는 것도 인덱스를 사용한다.


인덱스를 사용하지 않을 때

인덱스가 있고 WHERE 절에 열 이름이 나와도 인덱스를 사용하지 않는 경우가 있다.

인원 수가 1명 이상인 회원을 조회해 보자.

SELECT mem_id, mem_name, addr FROM member WHERE mem_number >= 1;

# mem_id, mem_name, addr
'APN', '에이핑크', '경기'
'BLK', '블랙핑크', '경남'
'GRL', '소녀시대', '서울'
'ITZ', '잇지', '경남'
'MMU', '마마무', '전남'
'OMY', '오마이걸', '서울'
'RED', '레드벨벳', '경북'
'SPC', '우주소녀', '서울'
'TWC', '트와이스', '서울'
'WMN', '여자친구', '경기'

이것은 MySQL이 인덱스 검색보다는 전체 테이블 검색이 낫겠다고 판단했기 때문이다.

이번에는 WHERE 절에 연산을 넣어보자. 

SELECT mem_id, mem_name, addr FROM member WHERE mem_number * 2 >= 14;

# mem_id, mem_name, addr
'GRL', '소녀시대', '서울'
'OMY', '오마이걸', '서울'
'SPC', '우주소녀', '서울'
'TWC', '트와이스', '서울'

WHERE 절에 연산이 있는 경우도 인덱스를 사용하지 않는다.

하지만 WHERE절이 아닌 14/2와 같이 WHERE절 연산에 영향을 미치지 않는 경우에는 인덱스를 사용한다.

SELECT mem_id, mem_name, addr FROM member WHERE mem_number  >= 14/2;

# mem_id, mem_name, addr
'OMY', '오마이걸', '서울'
'GRL', '소녀시대', '서울'
'TWC', '트와이스', '서울'
'SPC', '우주소녀', '서울'

즉 WHERE절에서는 아무런 연산을 하지 않는 것이 좋다.


인덱스 제거 실습

지금까지 생성한 인덱스를 제거하자. 먼저 인덱스의 이름을 확인하자.

SHOW INDEX FROM member;

# Table, Non_unique, Key_name, Seq_in_index, Column_name, Collation, Cardinality, Sub_part, Packed, Null, Index_type, Comment, Index_comment, Visible, Expression
'member', '0', 'PRIMARY', '1', 'mem_id', 'A', '10', NULL, NULL, '', 'BTREE', '', '', 'YES', NULL
'member', '0', 'idx_member_mem_name', '1', 'mem_name', 'A', '10', NULL, NULL, '', 'BTREE', '', '', 'YES', NULL
'member', '1', 'idx_member_addr', '1', 'addr', 'A', '5', NULL, NULL, '', 'BTREE', '', '', 'YES', NULL
'member', '1', 'idx_member_mem_number', '1', 'mem_number', 'A', '7', NULL, NULL, '', 'BTREE', '', '', 'YES', NULL

총 4개의 인덱스가 확인된다. 

지난 번에도 언급했지만, 클러스터형 인덱스와 보조 인덱스가 섞여있는 경우에는 보조 인덱스 먼저 삭제하는 것이 좋다. 이유는 클러스터형 인덱스를 먼저 삭제하면 데이터를 다시 제구성하기 때문에 시간이 더 오래 걸리기 때문이다.

DROP INDEX idx_member_mem_name ON member;
DROP INDEX idx_member_addr ON member;
DROP INDEX idx_member_mem_number ON member;

이번에는 클러스터형 인덱스를 삭제해 보자. 우선 PRIMARY KEY를 삭제해야 한다.

ALTER TABLE member
	DROP PRIMARY KEY;
    
17:18:12	ALTER TABLE member  DROP PRIMARY KEY	Error Code: 1553. Cannot drop index 'PRIMARY': needed in a foreign key constraint	0.015 sec

이유는 mem_id가 buy 테이블의 mem_id를 참조하고 있기 때문이다.

자 외래 키를 삭제하기 위해 information_schema 데이터베이스의 referential_constraints 테이블을 조회해서 알아보자.

SELECT table_name, constraint_name
	FROM information_schema.referential_constraints
    WHERE constraint_schema = 'market_db';
    
# TABLE_NAME, CONSTRAINT_NAME
'buy', 'buy_ibfk_1'

외래 키 이름을 알았으니 외래 키를 삭제 후 기본 키를 제거하자.

ALTER TABLE buy
	DROP FOREIGN KEY buy_ibfk_1;
ALTER TABLE member
	DROP PRIMARY KEY;

SHOW INDEX FROM member;

인덱스가 모두 삭제된 것을 확인할 수 있다.


3-3. 인덱스를 효과적으로 사용하는 방법

인덱스는 열 단위에 생성

하나의 열에 하나의 인덱스를 생성하는 것이 일반적이다.

물론 열에 2개 이상의 인덱스를 생성하거나 2개 이상의 열을 하나로 묶에서 하나의 인덱스로 만들 수는 있지만 하나의 열에 하나의 인덱스를 생성하는 것이 가장 일반적이다.

WHERE 절에서 사용되는 열에 인덱스를 만들어야 한다.

SELECT mem_id, mem_name, mem_number, addr
	FROM member
    WHERE mem_name = '에이핑크';

만약 member 테이블에서 이 SQL만 사용하고 위 열에 모두 인덱스가 설정되어 있다며 낭비이다. 실제로 WHERE절에서 사용되는 mem_name만 인덱스를 활용하기 때문이다.

WHERE 절에서 사용되더라도 자주 사용해야 가치가 있다.

인덱스가 자주 사용되지 않는다면 인덱스를 설정하지 않는 것이 더 좋을 수 있다.

데이터의 중복이 높은 열은 인덱스를 만들어도 별 효과가 없다

성별, 국번, 교통 수단 등 종류가 제한 적이 것에 인덱스가 설정되면 별 효과가 없다.

클러스터형 인덱스는 테이블당 하나만 생성할 수 있다.

사용하지 않는 인덱스는 제거한다.

'혼자공부하는 SQL' 카테고리의 다른 글

7. 스토어드 프로시저-2  (0) 2022.02.22
7. 스토어드 프로시저-1  (0) 2022.02.16
6. 인덱스-2  (0) 2022.02.10
6. 인덱스-1  (0) 2022.02.09
5. 테이블과 뷰-3  (0) 2022.02.08