반응형
해당 글에서는 테이블에서 스캔에 대해 이해하고 각각의 종류에 대해서 이해를 돕기 위해서 작성한 글입니다.
💡[참고] 테이블 전체 스캔과 테이블 인덱스 스캔의 간단한 요약
검색 | 방법 | 장점 | 단점 |
테이블 전체 스캔 (Full Table Scan) | 테이블의 모든 데이터를 읽어오는 방법 | 어떤 검색 조건을 사용하더라도 검색이 가능 | 검색 속도가 느릴 수 있음 |
테이블 인덱스 스캔 (Table Index Scan) | 인덱스를 이용하여 데이터를 읽어오는 방법 | 빠른 검색 속도 가능 | 인덱스 크기가 클 경우 느릴 수 있음 |
1) 테이블 전체 스캔(Table Full Scan)
💡 테이블 전체 스캔(Table Full Scan)이란?
- '인덱스(Index)를 사용하지 않고' 데이터를 검색하는 방식입니다. 이 경우 데이터베이스는 해당 테이블의 ‘모든 레코드’를 순차적으로 조회합니다.
- 테이블 전체 스캔의 경우 디스크 I/O의 비용이 많이 발생하며 대량의 데이터를 처리할 때는 시스템 성능에 부정적인 영향을 미칠 수 있습니다.
💡 테이블 전체 스캔 구문
- {테이블명}은 검색할 테이블의 이름값을 의미합니다.
SELECT *
FROM {테이블명};
[ 더 알아보기 ]
💡 테이블 전체 스캔(Table Full Scan)의 대안
1. 인덱스(Index)’를 사용하는 쿼리를 실행하는 방법이 있습니다. 인덱스(Index)를 사용하면 특정 조건에 해당하는 레코드만 읽어오기 때문에 데이터베이스의 성능을 향상 시킬수 있습니다.
2. 데이터베이스 ‘서버의 스펙’을 높여서 데이터베이스의 성능을 향상시킵니다.
3. 데이터베이스의 ‘파티셔닝(Partitioning) 기능’을 사용합니다.
💡데이터베이스의 파티셔닝(Partitioning)이란?
- 대용량의 데이터를 여러 개의 작은 데이터로 분할하여 저장할 수 있습니다. 이렇게 분할된 데이터는 더욱 빠른 검색 속도와 데이터 관리를 가능하게 합니다.
💡 인덱스 전체 스캔을 사용하는 경우
1. 대량의 데이터를 한 번에 처리를 해야 할 때 사용된다.
2. 인덱스를 사용하여 데이터를 가져오는 것보다 테이블 전체를 스캔하는 것이 빠른 경우 사용된다.
3. 테이블의 모든 데이터를 가져와야 하는 경우 사용된다.
2) 테이블 인덱스 스캔(Table Index Scan)
💡 테이블 인덱스 스캔(Table Index Scan)이란?
- ‘인덱스’를 사용하여 데이터를 검색하는 방식입니다.
- 인덱스는 데이터베이스 테이블에서 ‘특정 열’에 대한 정보를 가지고 있기 때문에 해당 열을 사용하여 검색할 경우 인덱스 스캔을 사용할 수 있습니다.
💡 테이블 인덱스 스캔 구문
- {테이블명}은 검색할 테이블의 이름을, {인덱스 컬럼}은 검색에 사용할 인덱스 컬럼을, {검색값}은 검색할 값을 의미합니다.
SELECT *
FROM {테이블명}
WHERE {인덱스 컬럼} = {검색값};
[ 더 알아보기 ]
💡 인덱스란?
- 데이터베이스 테이블의 특정 컬럼에 대한 검색 속도를 높이기 위해 사용되는 데이터 구조입니다.
- 이를 이용해 데이터베이스에서 원하는 레코드를 빠르게 찾을 수 있습니다. 인덱스를 사용하면 데이터베이스 쿼리의 성능이 대폭 개선되지만, 인덱스를 사용하는 것 자체가 추가적인 처리 비용을 발생시키기 때문에 적절한 인덱스를 설정해야 합니다.
1. 인덱스 스캔 SQL문
💡 인덱스 스캔은 테이블에서 하나 이상의 열(컬럼)을 선택하여서 지정이 가능합니다.
💡 아래의 구문에서는 {index_name}은 생성할 index의 이름, {table_name}은 index를 생성할 테이블의 이름, {column_name}은 index를 생성할 열을 의미합니다.
1.1. 테이블의 인덱스 조회
💡 postgreSQL에서 인덱스를 조회하는 구문입니다.
SELECT *
FROM pg_indexes
WHERE tablename = '{테이블명}';
1.2. 인덱스 생성
💡 SQL문에서 인덱스명은 생성할 인덱스의 이름, 테이블명은 인덱스를 생성할 테이블의 이름, 컬럼명은 인덱스를 생성할 컬럼의 이름입니다.
CREATE INDEX {인덱스명} ON {테이블명} ({컬럼명});
1.3. 인덱스 수정
💡 이미 생성된 인덱스를 수정할 때는 ALTER문을 사용합니다.
ALTER INDEX {인덱스명} ON {테이블명} {수정할 내용};
[참고] 수정할 내용에 대한 정의
구분 | 설명 |
RENAME TO {새 인덱스명} | 이미 생성된 인덱스의 이름을 변경할 때 사용하는 구문입니다. |
ADD {컬럼명} | 이미 생성된 인덱스에 새로운 컬럼을 추가할 때 사용하는 구문입니다. |
DROP {컬럼명} | 이미 생성된 인덱스에서 컬럼을 삭제할 때 사용하는 구문입니다. |
1.4. 인덱스 삭제
💡 이미 생성된 인덱스를 삭제할 때는 DROP문을 사용합니다.
DROP INDEX {인덱스명};
3. 인덱스 생성 유의점
유의점 | 설명 |
인덱스를 생성해야 할 필요성을 고려해야 합니다. | - 인덱스는 검색 속도를 향상시키지만 생성되는 인덱스가 많을수록 데이터베이스의 ‘쓰기 속도’는 저하됩니다. - 인덱스를 생성하기 전에 해당 필드가 자주 검색되는지, 데이터베이스에 쓰기 작업이 얼마나 자주 발생하는지 고려해야 합니다. |
인덱스의 크기를 고려해야 합니다. | - 인덱스를 생성할 때 해당 필드의 크기가 인덱스의 크기에 영향을 미칩니다. - 이를 고려하지 않으면 인덱스가 데이터베이스의 메모리를 많이 차지하여 성능 저하를 초래할 수 있습니다. |
인덱스 생성 시 관련된 테이블의 상태를 고려해야 합니다. | - 인덱스를 생성하기 전에 데이터베이스의 테이블 상태를 고려해야 합니다. - 예를 들어, 이미 존재하는 인덱스를 수정하거나 삭제하면 해당 인덱스를 사용하는 쿼리가 실패할 수 있습니다. |
인덱스를 생성할 때, 데이터베이스의 성능을 고려해야 합니다. | - 인덱스를 생성할 때 데이터베이스의 성능을 최적화하는 방법을 고려해야 합니다. - 예를 들어, 인덱스를 생성할 때, 해당 필드의 데이터 형식에 따라 인덱스 생성 방법이 달라질 수 있습니다. |
인덱스를 주기적으로 유지 보수해야 합니다. | - 인덱스를 생성하면 데이터베이스의 검색 속도가 향상됩니다. - 하지만 데이터베이스의 내용이 변경되면 인덱스도 함께 변경해야 합니다. 따라서 인덱스를 주기적으로 유지 보수해야 합니다. |
3) 인덱스 스캔의 종류
1. 인덱스 스캔의 종류 요약
인덱스 종류 | 설명 | 장점 | 단점 |
인덱스 전체 스캔 (Index Full Scan) | 인덱스의 모든 데이터를 읽어오는 방법 | 인덱스 크기가 작은 경우 빠른 검색 가능 | 테이블의 크기가 큰 경우 전체 테이블 스캔보다 느릴 수 있음 |
인덱스 범위 스캔 (Index Range Scan) | 인덱스의 일부 데이터만 읽어오는 방법으로, 인덱스의 범위를 지정하여 빠른 검색 가능 | 인덱스의 크기와 테이블의 크기에 관계없이 빠른 검색 가능 | 검색 범위가 넓을 경우 느릴 수 있음 |
인덱스 고유 스캔 (Index Unique Scan) | 인덱스의 유일한 값을 검색하는 방법 | 인덱스의 크기와 테이블의 크기에 관계없이 빠른 검색 가능 | 인덱스 컬럼이 유일한 값을 가지고 있을 때만 사용 가능 |
인덱스 루스 스캔 (Index Loose Scan) | 인덱스의 일부 데이터만 읽어오는 방법으로, 인덱스의 범위를 지정하지 않고 검색을 수행 | 인덱스의 크기와 테이블의 크기에 관계없이 빠른 검색 가능 | 정확도가 떨어질 수 있음 |
인덱스 병합 스캔 (Index Merge Scan) | 여러 개의 인덱스를 병합하여 검색하는 방법 | 복잡한 검색 조건을 처리할 수 있음 | 인덱스의 크기가 작은 경우에만 유용하며, 병합에 시간이 걸릴 수 있음 |
[ 더 알아보기 ]
💡 데이터베이스에서 비용(Cost)의 의미
- 시스템의 성능, 안정성, 보안, 유지보수 등을 유지하고 개선하기 위해 지출되는 비용을 의미합니다. 데이터베이스 비용은 하드웨어, 소프트웨어, 인력, 보안, 유지보수 비용의 요소로 포함되어 있습니다.
2. 인덱스 전체 스캔(Index Full Scan)
💡 인덱스 전체 스캔(Index Full Scan) 이란?
- 인덱스를 사용하지 않고 ‘전체 인덱스’를 읽어서 검색하는 방법을 의미합니다.
- 데이터가 적을 때는 빠르게 처리가 될 수 있으나 데이터가 많을 때는 많은 시간이 걸릴 수 있습니다.
- 인덱스 전체 스캔의 경우 데이터베이스의 성능에 영향을 미칠 수 있으며 인덱스를 효율적으로 사용하여 인덱스 전체 스캔이 발생하지 않도록 해야 합니다.
💡 인덱스 전체 스캔(Index Full Scan) 구문
- {테이블명}은 검색할 테이블의 이름을, {인덱스 컬럼}은 검색에 사용할 인덱스 컬럼을, {검색값}은 검색할 값을 지정합니다.
SELECT *
FROM {테이블명}
-- 인덱스가 아닌 컬럼을 조건으로 함.
WHERE {조건};
💡 인덱스 전체 스캔의 발생 시기
1. ‘인덱스를 사용하지 않고’ 전체 테이블을 검색해야 할 때 발생됩니다.
2. 인덱스의 ‘selectivity가 매우 낮아서’ ‘일부 레코드’만 가져올 때 발생됩니다.
[ 더 알아보기 ]
💡 선택성(selectivity) 란?
- 인덱스 컬럼의 값이 얼마나 유일한지에 대한 지표입니다.
- 인덱스 컬럼이 ‘성별’인 경우 ‘남자’와 ‘여자’의 두 가지 값만 가지고 있다면 선택성이 낮습니다.
- 인덱스 컬럼이 ‘이메일’인 경우 모든 값들이 유니크한 값을 가지고 있을 가능성이 높기에 선택성이 높습니다.
💡 인덱스 컬럼을 지정할 때에 선택성이 높은 인덱스를 사용하는 것이 더 효과적입니다. ⭐️
💡 인덱스 전체 스캔의 예시
- 고객 테이블에서 2020년 1월 01일부터 2020년 12월 31일까지 구매내역을 조회하는 SQL문입니다.
SELECT * FROM 고객 WHERE 구매일자 >= '2020-01-01' AND 구매일자 <= '2020-12-31';
💡 위에 SQL문의 인덱스 크기가 매우 크거나 해당 기간 동안 거래가 많은 경우 인덱스를 사용하지 않고 테이블 전체 스캔을 사용하는 것이 효율적입니다.
SELECT * FROM 고객 WHERE 구매일자 > '2020-01-01';
3. 인덱스 범위 스캔(Index Range Scan)
💡 인덱스 범위 스캔(Index Range Scan)이란?
- ‘인덱스의 일부’만 스캔하는 방법을 의미합니다. 데이터가 많은 경우 전체 스캔보다 효율적일 수 있습니다.
- 해당 스캔방식의 경우 특정 범위 내의 레코드만 읽어 들이기 때문에 비용이 적게 듭니다.
💡 인덱스 범위 스캔(Index Range Scan) 구문
- {테이블명}은 검색할 테이블의 이름을, {인덱스 컬럼}은 검색에 사용할 인덱스 컬럼을, {검색 시작값}은 검색할 범위의 시작값을, {검색 종료값}은 검색할 범위의 종료값을 의미합니다.
SELECT *
FROM {테이블명}
WHERE {인덱스 컬럼} BETWEEN {검색 시작값} AND {검색 종료값};
💡 인덱스 범위 스캔 예시
- 2020년 1월 01일부터 2020년 12월 31일까지 구매내역을 조회하는 SQL문입니다.
SELECT *
FROM 고객
WHERE 구매일자 BETWEEN '2020-01-01' AND '2020-12-31';
💡 인덱스 범위 스캔의 발생시기
1. WHERE 절에서 범위 검색을 수행할 때 발생됩니다.
2. ORDER BY 절에서 정렬할 때 발생됩니다.
3. JOIN 연산을 수행할 때 발생됩니다.
💡 인덱스의 선택성(selectivity)이 매우 낮은 경우 전체 스캔이 발생할 수 있기에 선택성을 고려하여 인덱스를 설계해야 합니다.
4. 인덱스 고유 스캔(Index Unique Scan)
💡 인덱스 고유 스캔(Index Unique Scan) 이란?
- 인덱스에서 중복되지 않는 ‘유일한 값’을 검색하는 방법을 의미합니다. 해당 방법은 하나의 값만 읽어 들이기 때문에 비용이 가장 적게 듭니다.
- 고유 인덱스는 유일성을 보장하기 때문에 인덱스 전체 스캔보다 빠를 수 있으나 ‘단일 값’을 검색할 때에만 사용할 수 있기 때문에 제한적인 경우에만 사용됩니다.
💡 인덱스 고유 스캔(Index Unique Scan) 구문
- {테이블명}은 검색할 테이블의 이름을, {인덱스 컬럼}은 검색에 사용할 인덱스 컬럼을, {검색값}은 검색할 값입니다.
SELECT *
FROM {테이블명}
WHERE {인덱스 컬럼} = {검색값};
💡 인덱스 고유 스캔 예시
- 고객이라는 테이블에서 ID가 1인 고객의 정보를 조회하는 SQL문입니다.
SELECT *
FROM 고객
WHERE ID = 1;
💡 인덱스 고유 스캔의 발생시기
1. PRIMARY KEY 또는 UNIQUE 인덱스를 사용하여 검색할 때 발생합니다.
2. 인덱스에서 단일 값을 검색할 때 발생합니다.
5. 인덱스 루스 스캔(Index Loose Scan)
💡 인덱스 루스 스캔(Index Loose Scan)이란?
- 인덱스 레인지 스캔과 비슷하게 ‘특정 인덱스 범위’만 스캔하는 방식과 비슷하지만 ‘중간중간 필요 없는 인덱스 키 값을 건너뛰고’ 다음으로 넘어가서 검색하는 방식을 의미합니다.
💡 인덱스 루스 스캔(Index Loose Scan) 구문
- {테이블명}은 검색할 테이블의 이름을, {인덱스 컬럼}은 검색에 사용할 인덱스 컬럼을, {검색어}는 검색할 텍스트를 의미합니다.
SELECT *
FROM {테이블명}
WHERE {인덱스 컬럼} LIKE '%{검색어}%';
💡 인덱스 루스 스캔 예시
- 인덱스 컬럼의 값이 {값}으로 시작하는 데이터를 조회하는 SQL 문입니다.
SELECT *
FROM 고객
WHERE 이름 LIKE '김%';
💡 인덱스 루스 스캔의 발생시기
- WHERE 절에 LIKE 키워드를 사용하여 특정 문자열을 검색하는 경우 발생합니다.
6. 인덱스 병합 스캔(Index Merge Scan)
💡 인덱스 병합 스캔(Index Merge Scan)이란?
- ‘두 개 이상의 인덱스를 병합하여 검색하는 방법’을 의미합니다.
- 해당 방식은 각 인덱스를 병합하는데 시간이 걸리기 때문에 전체적인 속도가 느릴 수 있으나 각각의 인덱스를 사용하는 것보다 효율적입니다.
💡 인덱스 병합 스캔(Index Merge Scan) 구문
- {테이블명}은 검색할 테이블의 이름을, {인덱스 컬럼1}, {인덱스 컬럼2}은 검색에 사용할 인덱스 컬럼을, {검색값 1}, {검색값 2}는 검색할 값입니다.
SELECT *
FROM {테이블명}
WHERE {인덱스 컬럼1} = {검색값1}
AND {인덱스 컬럼2} = {검색값2};
💡 인덱스 병합 스캔 예시
- 고객이라는 테이블에서 ID가 1이고, 이름이 '김철수'인 고객의 정보를 조회하는 SQL 문입니다.
SELECT *
FROM 고객
WHERE ID = 1 AND 이름 = '김철수';
💡 인덱스 병합 스캔의 발생시기
1. OR 조건이 포함된 쿼리에서 각각의 조건에 해당하는 인덱스를 사용하는 경우에 발생합니다.
2. UNION ALL 연산자를 수행하는 경우에 발생합니다.
오늘도 감사합니다. 😀
반응형
'DB > 이론 및 문법' 카테고리의 다른 글
[DB] 관계형 데이터베이스 키(Key) 이해하기 (0) | 2023.09.09 |
---|---|
[DB/Postgres] PL/pgSQL 구성하기 -2 : DBeaver 기반 구축 및 활용 (0) | 2023.04.17 |
[DB/Postgres] GROUP BY, ORDER BY, LIMIT 이해하기 -1 (0) | 2023.04.08 |
[DB/Postgres] PL/pgSQL이해하기 -1 : Function, Stored Procedure (0) | 2023.04.08 |
[DB/Postgres] 서브쿼리(Subquery) / WITH 절 이해하기 -1 (0) | 2023.04.06 |