웹사이트 검색

MySQL에서 인덱스를 사용하는 방법


저자는 Write for DOnations 프로그램을 선택했습니다.

소개

관계형 데이터베이스는 수백만 개의 행을 포함하는 대규모 데이터베이스를 포함하여 모든 크기의 데이터 작업에 사용할 수 있습니다. SQL(Structured Query Language)은 특정 기준에 따라 데이터베이스 테이블에서 특정 행을 찾는 간결하고 직접적인 방법을 제공합니다. 데이터베이스가 커짐에 따라 건초 더미에서 바늘을 찾는 것과 유사하게 데이터베이스 내에서 특정 행을 찾는 것이 점점 더 어려워집니다.

데이터베이스가 광범위한 쿼리 조건을 수용하는 기능으로 인해 데이터베이스 엔진이 어떤 쿼리가 가장 일반적일지 예측하기가 어렵습니다. 엔진은 크기에 관계없이 데이터베이스 테이블에서 행을 효율적으로 찾을 수 있도록 준비되어야 합니다. 그러나 데이터가 증가하면 검색 성능이 저하될 수 있습니다. 데이터 세트가 클수록 데이터베이스 엔진이 쿼리와 일치하는 문서를 빨리 찾기가 더 어려워집니다.

데이터베이스 관리자는 인덱스를 사용하여 데이터베이스 엔진을 지원하고 성능을 향상시킬 수 있습니다.

이 자습서에서는 인덱스가 무엇인지, 인덱스를 생성하는 방법 및 인덱스가 데이터베이스를 쿼리하는 데 사용되는지 여부에 대해 알아봅니다.

전제 조건

이 가이드를 따르려면 SQL 기반 RDBMS(관계형 데이터베이스 관리 시스템)를 실행하는 컴퓨터가 필요합니다. 이 가이드의 지침과 예제는 다음 환경을 사용하여 검증되었습니다.

  • Ubuntu 20.04용 초기 서버 설정 가이드에 설명된 대로 관리 권한이 있는 루트가 아닌 사용자와 UFW로 구성된 방화벽이 있는 Ubuntu 20.04를 실행하는 서버
  • 3단계에 설명된 대로 서버에 MySQL을 설치하고 보호합니다.
  • How To SELECT Rows FROM Tables in SQL 가이드에 설명된 대로 데이터베이스에서 데이터를 검색하기 위해 SELECT 쿼리를 실행하는 것과 관련된 기본 지식.

참고: 많은 RDBMS는 고유한 SQL 구현을 사용합니다. 이 자습서에 설명된 명령은 대부분의 RDBMS에서 작동하지만 인덱스는 표준 SQL 구문의 일부가 아니므로 MySQL 이외의 시스템에서 테스트하는 경우 정확한 구문이나 출력이 다를 수 있습니다.

또한 인덱스 사용을 연습할 수 있도록 샘플 데이터가 로드된 일부 테이블이 있는 데이터베이스가 필요합니다. MySQL 서버에 연결하고 이 가이드의 예제에 사용된 테스트 데이터베이스를 만드는 방법에 대한 자세한 내용은 다음 MySQL에 연결 및 샘플 데이터베이스 설정 섹션을 참조하십시오.

MySQL에 연결 및 샘플 데이터베이스 설정

이 섹션에서는 이 가이드의 예제를 따를 수 있도록 MySQL 서버에 연결하고 샘플 데이터베이스를 생성합니다.

SQL 데이터베이스 시스템이 원격 서버에서 실행되는 경우 로컬 시스템에서 서버로 SSH합니다.

  1. ssh sammy@your_server_ip

그런 다음 MySQL 서버 프롬프트를 열고 sammyMySQL 사용자 계정의 이름으로 바꿉니다.

  1. mysql -u sammy -p

indexes라는 이름의 데이터베이스를 만듭니다.

  1. CREATE DATABASE indexes;

데이터베이스가 성공적으로 생성되면 다음과 같은 출력을 받게 됩니다.

Output
Query OK, 1 row affected (0.01 sec)

indexes 데이터베이스를 선택하려면 다음 USE 문을 실행합니다.

  1. USE indexes;

다음 출력을 받게 됩니다.

Output
Database changed

데이터베이스를 선택한 후 그 안에 샘플 테이블을 만들 수 있습니다. 이 가이드에서는 가상 직원 데이터베이스를 사용하여 현재 직원 및 작업 장치에 대한 세부 정보를 저장합니다.

테이블 employees에는 데이터베이스의 직원에 대한 단순화된 데이터가 포함됩니다. 다음 열을 포함합니다.

  • employee_id: 이 열에는 int 데이터 유형으로 표시되는 직원 식별자가 있습니다. 이 열은 테이블의 기본 키가 되며 각 값은 해당 행의 고유 식별자가 됩니다.
  • first_name: 이 열에는 각 직원의 이름이 포함되며 최대 50varchar 데이터 유형을 사용하여 표현됩니다.< /리>
  • last_name: 이 열에는 각 직원의 성이 있으며 최대 50 문자로 varchar 데이터 유형을 사용하여 표현됩니다.< /리>
  • device_serial: 이 열에는 직원에게 할당된 컴퓨터의 일련 번호가 있으며 최대 15varchar 데이터 유형을 사용하여 표현됩니다. > 문자.
  • salary: 이 열은 숫자 데이터를 저장하는 int 데이터 유형을 사용하여 표현된 각 직원의 급여를 보유합니다.

다음 명령을 사용하여 샘플 테이블을 생성합니다.

  1. CREATE TABLE employees (
  2. employee_id int,
  3. first_name varchar(50),
  4. last_name varchar(50),
  5. device_serial varchar(15),
  6. salary int
  7. );

다음 출력이 인쇄되면 테이블이 생성된 것입니다.

Output
Query OK, 0 rows affected (0.00 sec)

그런 다음 INSERT INTO 작업을 실행하여 일부 샘플 데이터가 있는 employees 테이블을 로드합니다.

  1. INSERT INTO employees VALUES
  2. (1, 'John', 'Smith', 'ABC123', 60000),
  3. (2, 'Jane', 'Doe', 'DEF456', 65000),
  4. (3, 'Bob', 'Johnson', 'GHI789', 70000),
  5. (4, 'Sally', 'Fields', 'JKL012', 75000),
  6. (5, 'Michael', 'Smith', 'MNO345', 80000),
  7. (6, 'Emily', 'Jones', 'PQR678', 85000),
  8. (7, 'David', 'Williams', 'STU901', 90000),
  9. (8, 'Sarah', 'Johnson', 'VWX234', 95000),
  10. (9, 'James', 'Brown', 'YZA567', 100000),
  11. (10, 'Emma', 'Miller', 'BCD890', 105000),
  12. (11, 'William', 'Davis', 'EFG123', 110000),
  13. (12, 'Olivia', 'Garcia', 'HIJ456', 115000),
  14. (13, 'Christopher', 'Rodriguez', 'KLM789', 120000),
  15. (14, 'Isabella', 'Wilson', 'NOP012', 125000),
  16. (15, 'Matthew', 'Martinez', 'QRS345', 130000),
  17. (16, 'Sophia', 'Anderson', 'TUV678', 135000),
  18. (17, 'Daniel', 'Smith', 'WXY901', 140000),
  19. (18, 'Mia', 'Thomas', 'ZAB234', 145000),
  20. (19, 'Joseph', 'Hernandez', 'CDE567', 150000),
  21. (20, 'Abigail', 'Smith', 'FGH890', 155000);

데이터베이스는 성공 메시지로 응답합니다.

Output
Query OK, 20 rows affected (0.010 sec) Records: 20 Duplicates: 0 Warnings: 0

참고: 데이터 세트는 인덱스의 성능 영향을 직접적으로 설명하기에 충분히 크지 않습니다. 그러나 이 데이터 세트는 MySQL이 쿼리를 수행하고 결과를 얻기 위해 통과하는 행의 양을 제한하기 위해 인덱스를 사용하는 방법을 보여줍니다.

이것으로 가이드의 나머지 부분을 따르고 MySQL에서 인덱스를 사용할 준비가 된 것입니다.

인덱스 소개

일반적으로 MySQL 데이터베이스에 대해 쿼리를 실행할 때 데이터베이스는 테이블의 모든 행을 하나씩 통과해야 합니다. 예를 들어 Smith와 일치하는 직원 성을 검색하거나 급여가 $100000보다 높은 모든 직원을 검색할 수 있습니다. 테이블의 모든 행은 조건과 일치하는지 확인하기 위해 하나씩 검사됩니다. 그렇다면 반환된 행 목록에 추가됩니다. 그렇지 않은 경우 MySQL은 전체 테이블을 탐색할 때까지 후속 행을 스캔합니다.

일치하는 행을 찾는 이 방법은 효과적이지만 테이블 크기가 증가함에 따라 속도가 느려지고 리소스를 많이 사용할 수 있습니다. 결과적으로 이 접근 방식은 자주 또는 빠른 데이터 액세스가 필요한 대형 테이블이나 쿼리에 적합하지 않을 수 있습니다.

대형 테이블 및 쿼리의 성능 문제를 해결하기 위해 인덱스를 사용할 수 있습니다. 인덱스는 테이블 행과 별도로 데이터의 정렬된 하위 집합만 저장하는 고유한 데이터 구조입니다. 이를 통해 데이터베이스 엔진은 값을 조회하거나 특정 필드 또는 필드 집합에 대해 주문할 때 보다 빠르고 효율적으로 작동할 수 있습니다.

employees 테이블을 예로 사용하여 실행할 수 있는 일반적인 쿼리 중 하나는 성으로 직원을 찾는 것입니다. 인덱스가 없으면 MySQL은 테이블에서 모든 직원을 검색하고 성이 쿼리와 일치하는지 확인합니다. 그러나 인덱스를 사용할 때 MySQL은 기본 테이블의 지정된 직원에 대한 행에 대한 포인터만 포함하는 별도의 성 목록을 보유합니다. 그런 다음 해당 인덱스를 사용하여 전체 테이블을 스캔하지 않고 결과를 검색합니다.

색인은 전화번호부에 비유할 수 있습니다. 책에서 이름이 John Smith인 사람을 찾으려면 먼저 S로 시작하는 이름을 가진 사람들이 나열되어 있는 오른쪽 페이지로 이동한 다음 페이지에서 사람을 찾습니다. 이름은 Sm으로 시작합니다. 이러한 논리를 따르면 찾고 있는 사람과 일치하지 않는다는 사실을 알고 많은 항목을 빠르게 제거할 수 있습니다. 이 프로세스는 전화번호부의 데이터가 알파벳순으로 정렬되기 때문에 작동하며, 데이터가 데이터베이스에 직접 저장된 경우는 거의 없습니다. 데이터베이스 엔진의 인덱스는 전화번호부와 유사한 용도로 사용되며 데이터에 대한 참조를 사전순으로 정렬하여 데이터베이스가 필요한 행을 빠르게 찾을 수 있도록 도와줍니다.

MySQL에서 인덱스를 사용하면 여러 가지 이점이 있습니다. 가장 일반적인 것은 ORDER BY 절의 속도를 높이고 값 고유성을 적용하는 것입니다.

그러나 인덱스를 사용하면 일부 상황에서 최대 데이터베이스 성능이 저하될 수 있습니다. 인덱스는 데이터 검색 속도를 높이도록 설계되었으며 테이블 데이터와 함께 저장되는 추가 데이터 구조를 사용하여 구현됩니다. 이러한 구조는 데이터베이스가 변경될 때마다 최신 상태로 유지되어야 합니다. 이로 인해 SELECT 쿼리의 성능이 느려질 수 있으며 때때로 데이터베이스에 데이터를 쓰는 쿼리의 현저하게 느린 성능보다 더 중요할 수 있습니다.

애플리케이션의 성능이 저하되기 시작하는 경우와 같이 인덱스에 대한 명확한 필요성이 있는 경우에만 인덱스를 생성하는 것이 좋습니다. 생성할 인덱스를 선택할 때 가장 자주 실행되고 가장 시간이 오래 걸리는 쿼리를 고려하고 가장 많은 이점을 얻을 수 있는 쿼리 조건을 기반으로 인덱스를 구축합니다.

참고: 이 가이드는 일반적인 애플리케이션 및 인덱스 유형을 설명하는 MySQL의 데이터베이스 인덱스 주제를 소개하는 것을 목표로 합니다. 데이터베이스 엔진은 인덱스를 사용하여 데이터베이스 성능을 향상시키는 더 복잡한 시나리오를 지원하며, 이는 이 가이드의 범위를 벗어납니다. 데이터베이스 기능에 대한 자세한 설명은 인덱스에 대한 공식 MySQL 문서를 참조하는 것이 좋습니다.

다음 단계에서는 다양한 시나리오에 대해 다양한 유형의 인덱스를 생성합니다. 인덱스가 쿼리에서 사용되는지 확인하는 방법을 배웁니다. 마지막으로 필요한 경우 인덱스를 제거하는 방법을 배웁니다.

단일 열 인덱스 사용

단일 열 인덱스는 쿼리 성능을 최적화하는 데 사용할 수 있는 가장 일반적이고 간단한 인덱스 유형입니다. 이 유형의 인덱스는 데이터베이스가 단일 열의 값을 기반으로 데이터 세트를 필터링하는 쿼리 속도를 높이는 데 도움이 됩니다. 단일 열에 생성된 인덱스는 = 연산자를 사용한 정확한 일치 및 > 또는 < 연산자와의 비교를 포함하여 많은 조건부 쿼리의 속도를 높일 수 있습니다.

이전 단계에서 생성한 예제 데이터베이스에는 인덱스가 없습니다. 인덱스를 생성하기 전에 먼저 WHERE 절이 요청에만 사용될 때 데이터베이스가 employees 테이블에서 SELECT 쿼리를 처리하는 방법을 테스트합니다. 테이블의 데이터 하위 집합입니다.

급여가 정확히 $100,000인 직원을 찾고 싶다고 가정합니다. 다음 쿼리를 실행합니다.

  1. SELECT * FROM employees WHERE salary = 100000;

WHERE 절은 요청된 값과 일치하는 급여를 가진 직원의 정확한 일치를 요청합니다. 이 예에서 데이터베이스는 다음과 같이 응답합니다.

Output
+-------------+------------+-----------+---------------+--------+ | employee_id | first_name | last_name | device_serial | salary | +-------------+------------+-----------+---------------+--------+ | 9 | James | Brown | YZA567 | 100000 | +-------------+------------+-----------+---------------+--------+ 1 row in set (0.000 sec)

참고: 위의 출력에서 볼 수 있듯이 데이터베이스는 실행된 쿼리에 거의 즉각적으로 응답했습니다. 데이터베이스에 있는 소수의 샘플 행만 있으면 인덱스를 사용해도 쿼리 성능에 눈에 띄는 영향을 미치지 않습니다. 그러나 대규모 데이터 세트의 경우 쿼리를 실행한 후 데이터베이스에서 보고하는 쿼리 실행 시간에 상당한 변화가 있음을 관찰할 수 있습니다.

쿼리 출력으로 판단하면 데이터베이스 엔진이 테이블에서 일치하는 행을 찾는 문제에 어떻게 접근했는지 알 수 없습니다. 그러나 MySQL은 엔진이 EXPLAIN 문 쿼리를 실행하는 방법인 쿼리 계획에 대한 통찰력을 얻을 수 있는 방법을 제공합니다.

SELECT 쿼리에 대한 쿼리 계획에 액세스하려면 다음을 실행합니다.

  1. EXPLAIN SELECT * FROM employees WHERE salary = 100000;

EXPLAIN 명령은 MySQL에 SELECT 쿼리를 실행하도록 지시하지만 결과를 반환하는 대신 데이터베이스 엔진이 내부적으로 쿼리를 수행한 방법에 대한 정보를 표시합니다.

실행 계획은 다음과 유사합니다(표는 약간 다를 수 있음).

Output
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | employees | NULL | ALL | NULL | NULL | NULL | NULL | 20 | 10.00 | Using where | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec)

이 테이블 출력에서 열은 쿼리 실행의 여러 측면을 설명합니다. MySQL 버전에 따라 출력에 추가 열이 포함될 수 있지만 이 자습서의 경우 가장 중요한 정보는 다음과 같습니다.

  • possible_keys는 MySQL이 사용을 고려한 인덱스를 나열합니다. 이 경우에는 아무것도 없습니다(NULL).
  • key는 MySQL이 쿼리를 수행할 때 사용하기로 결정한 인덱스를 설명합니다. 이 경우 인덱스가 사용되지 않았습니다(NULL).
  • rows는 결과를 반환하기 전에 MySQL이 개별적으로 분석해야 했던 행 수를 보여줍니다. 여기서는 테이블에서 가능한 모든 행의 수에 해당하는 20입니다. 이는 MySQL이 반환된 단일 항목을 찾기 위해 employees 테이블의 모든 행을 스캔해야 했음을 의미합니다.
  • Extra는 쿼리 계획에 대한 추가 설명 정보를 표시합니다. 이 예에서 Using where 주석은 데이터베이스가 WHERE 문을 사용하여 테이블 내에서 직접 결과를 필터링했음을 의미합니다.

인덱스가 없는 상태에서 데이터베이스는 20 행을 스캔하여 하나를 검색해야 했습니다. 테이블에 수백만 개의 행이 포함된 경우 MySQL은 이를 하나씩 처리해야 하므로 쿼리 성능이 저하됩니다.

참고: 최신 MySQL 버전은 EXPLAIN을 사용할 때 집합에 1행, 출력에 1경고를 표시하는 반면 이전 MySQL 버전과 MySQL은 호환되는 데이터베이스는 종종 단순히 집합의 1행을 대신 표시합니다. 경고는 문제의 징후가 아닙니다. MySQL은 경고 메커니즘을 사용하여 쿼리 계획에 대한 추가 확장 정보를 제공합니다. 이러한 추가 정보의 사용은 이 자습서의 범위를 벗어납니다. MySQL 설명서의 확장 EXPLAIN 출력 형식 페이지에서 해당 동작에 대해 자세히 알아볼 수 있습니다.

방금 실행한 SELECT 쿼리는 WHERE 급여 = 100000이라는 정확한 쿼리 조건을 사용했습니다. 다음으로 비교 조건으로 데이터베이스가 유사하게 동작하는지 확인해 봅시다. 급여가 70000보다 낮은 직원 검색:

  1. SELECT * FROM employees WHERE salary < 70000;

이번에 데이터베이스는 John SmithJane Doe에 대해 두 개의 행을 반환했습니다.

Output
+-------------+------------+-----------+---------------+--------+ | employee_id | first_name | last_name | device_serial | salary | +-------------+------------+-----------+---------------+--------+ | 1 | John | Smith | ABC123 | 60000 | | 2 | Jane | Doe | DEF456 | 65000 | +-------------+------------+-----------+---------------+--------+ 8 rows in set (0.000 sec)

그러나 쿼리 실행을 이해하기 위해 EXPLAIN을 사용하면 다음과 같습니다.

  1. EXPLAIN SELECT * FROM employees WHERE salary < 70000;

테이블이 이전 쿼리와 거의 동일하다는 것을 알 수 있습니다.

Output
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | employees | NULL | ALL | NULL | NULL | NULL | NULL | 20 | 33.33 | Using where | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec)

이전 쿼리와 마찬가지로 MySQL은 테이블의 모든 20 행을 스캔하여 쿼리의 WHERE 절을 통해 요청한 행을 찾습니다. 리턴되는 행의 수가 테이블의 전체 행 수에 비해 적더라도 데이터베이스 엔진은 이를 찾기 위해 많은 작업을 수행해야 합니다.

이를 해결하기 위해 salary 열에 대한 인덱스를 생성할 수 있습니다. 이 인덱스는 특히 salary 데이터에 대해 고도로 최적화된 추가 데이터 구조를 유지하도록 MySQL에 지시합니다. 코드>직원 테이블. 이렇게 하려면 다음 쿼리를 실행합니다.

  1. CREATE INDEX salary ON employees(salary);

CREATE INDEX 문 구문에는 다음이 필요합니다.

  • 이 경우 salary인 인덱스 이름입니다. 이름은 단일 테이블 내에서 고유해야 하지만 동일한 데이터베이스의 여러 테이블에서 반복될 수 있습니다.
  • 인덱스가 생성되는 테이블 이름입니다. 이 경우 직원입니다.
  • 인덱스가 생성된 열 목록입니다. 여기에서는 salary라는 단일 열을 사용하여 인덱스를 작성합니다.

참고: MySQL 사용자 권한에 따라 CREATE INDEX 명령을 실행할 때 오류가 발생할 수 있습니다. 코드>. 사용자에게 INDEX 권한을 부여하려면 MySQL에 루트로 로그인하고 다음 명령을 실행하여 필요에 따라 MySQL 사용자 이름과 호스트를 바꿉니다.

  1. GRANT INDEX on *.* TO 'sammy'@'localhost';
  2. FLUSH PRIVILEGES;

사용자 권한을 업데이트한 후 루트로 로그아웃했다가 사용자로 다시 로그인하고 CREATE INDEX 문을 다시 실행합니다.

데이터베이스는 색인이 성공적으로 생성되었는지 확인합니다.

Output
Query OK, 0 rows affected (0.024 sec) Records: 0 Duplicates: 0 Warnings: 0

인덱스가 있는 상태에서 이전 쿼리를 반복하여 변경된 사항이 있는지 확인합니다. 급여가 정확히 100000인 단일 직원을 검색하여 시작합니다.

  1. SELECT * FROM employees WHERE salary = 100000;

결과는 이전과 동일하며 James Brown만 반환됩니다.

Output
+-------------+------------+-----------+---------------+--------+ | employee_id | first_name | last_name | device_serial | salary | +-------------+------------+-----------+---------------+--------+ | 9 | James | Brown | YZA567 | 100000 | +-------------+------------+-----------+---------------+--------+ 1 row in set (0.000 sec)

그러나 MySQL에 쿼리에 어떻게 접근했는지 설명을 요청하면 이전과 몇 가지 차이점이 표시됩니다. 다음과 같이 EXPLAIN 쿼리를 실행합니다.

  1. EXPLAIN SELECT * FROM employees WHERE salary = 100000;

이번에는 출력이 다음과 같이 인쇄됩니다.

Output
+----+-------------+-----------+------------+------+---------------+--------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+--------+---------+-------+------+----------+-------+ | 1 | SIMPLE | employees | NULL | ref | salary | salary | 5 | const | 1 | 100.00 | NULL | +----+-------------+-----------+------------+------+---------------+--------+---------+-------+------+----------+-------+ 1 row in set, 1 warning (0.00 sec)

MySQL은 possible_keys에 표시된 하나의 가능한 키에서 생성한 인덱스인 salary라는 키를 사용하기로 결정했다고 선언합니다. 이제 rows 열에 20 대신 1이 표시됩니다. 인덱스를 사용했기 때문에 데이터베이스는 데이터베이스의 모든 행을 스캔하지 않고 요청된 단일 행을 즉시 반환할 수 있습니다. 이제 Extra 열은 WHERE 사용을 언급하지 않습니다. 쿼리를 수행하기 위해 기본 테이블을 반복하고 쿼리 조건에 대해 각 행을 확인할 필요가 없었기 때문입니다.

작은 샘플 데이터 세트를 사용하면 인덱스 사용의 영향이 그다지 눈에 띄지 않습니다. 그러나 결과를 검색하는 데 데이터베이스 작업이 훨씬 덜 필요했으며 이 변경의 영향은 더 큰 데이터 세트에서 중요할 것입니다.

급여가 70000보다 낮은 직원을 검색하는 두 번째 쿼리를 다시 실행하여 인덱스가 여기에서도 사용되는지 확인하십시오.

다음 쿼리를 실행합니다.

  1. SELECT * FROM employees WHERE salary < 70000;

John SmithJane Doe에 대해 동일한 두 행이 반환됩니다.

Output
+-------------+------------+-----------+---------------+--------+ | employee_id | first_name | last_name | device_serial | salary | +-------------+------------+-----------+---------------+--------+ | 1 | John | Smith | ABC123 | 60000 | | 2 | Jane | Doe | DEF456 | 65000 | +-------------+------------+-----------+---------------+--------+ 8 rows in set (0.000 sec)

그러나 다음과 같이 EXPLAIN을 사용하는 경우:

  1. EXPLAIN SELECT * FROM employees WHERE salary < 70000;

테이블은 동일한 쿼리의 이전 실행과 다릅니다.

Output
+----+-------------+-----------+------------+-------+---------------+--------+---------+------+------+----------+-----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+-------+---------------+--------+---------+------+------+----------+-----------------------+ | 1 | SIMPLE | employees | NULL | range | salary | salary | 5 | NULL | 2 | 100.00 | Using index condition | +----+-------------+-----------+------------+-------+---------------+--------+---------+------+------+----------+-----------------------+ 1 row in set, 1 warning (0.00 sec)

key 열은 MySQL이 쿼리를 수행하기 위해 인덱스를 사용했음을 알려줍니다. rows에서는 두 개의 행만 분석하여 결과를 반환했습니다. 이번에는 Extra 열에 인덱스 조건 사용이 표시됩니다. 즉, 이 특별한 경우 MySQL은 인덱스를 사용하여 필터링한 다음 기본 테이블을 이미 검색하는 데만 사용했습니다. 일치하는 행.

참고: 때로는 인덱스가 있고 사용할 수 있어도 MySQL이 인덱스를 사용하지 않기로 결정합니다. 예를 들어 다음을 실행하는 경우:

  1. EXPLAIN SELECT * FROM employees WHERE salary < 140000;

실행 계획은 다음과 같습니다.

Output
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | employees | NULL | ALL | salary | NULL | NULL | NULL | 20 | 80.00 | Using where | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec)

salarypossible_keys에 나열되더라도 빈 key 열(NULL 읽기)은 MySQL이 20 스캔 행으로 확인할 수 있는 인덱스를 사용합니다. 데이터베이스 쿼리 플래너는 가능한 인덱스에 대해 각 쿼리를 분석하여 가장 빠른 실행 경로를 결정합니다. 인덱스에 액세스하는 비용이 사용 이점보다 큰 경우(예: 쿼리가 원본 테이블 데이터의 상당 부분을 반환하는 경우) 데이터베이스는 전체 테이블 스캔을 수행하는 것이 실제로 더 빠르다고 결정할 수 있습니다.

마찬가지로 Using index condition 또는 Using where와 같은 Extra 열의 주석은 데이터베이스 엔진이 쿼리를 실행한 방법을 더 자세히 설명합니다. . 컨텍스트에 따라 데이터베이스는 쿼리를 실행하는 다른 방법을 선택할 수 있으며 인덱스 조건 사용 주석이 없거나 다른 주석이 있는 출력이 있을 수 있습니다. 이는 인덱스가 제대로 사용되지 않는다는 의미가 아니라 데이터베이스가 행에 액세스하는 다른 방법이 더 효과적일 것이라고 결정했다는 의미입니다.

이 섹션에서는 단일 열에 대한 필터링에 의존하는 SELECT 쿼리의 성능을 개선하기 위해 단일 열 인덱스를 만들고 사용했습니다. 다음 섹션에서는 인덱스를 사용하여 지정된 열의 값에서 고유성을 보장하는 방법을 살펴봅니다.

고유 인덱스를 사용하여 데이터 중복 방지

마지막 섹션에서 살펴본 것처럼 인덱스의 일반적인 용도 중 하나는 데이터베이스 엔진이 동일한 결과를 얻기 위해 더 적은 작업을 수행하도록 함으로써 데이터를 보다 효율적으로 검색하는 것입니다. 또 다른 목적은 인덱스가 정의된 테이블 부분의 데이터가 반복되지 않도록 하는 것입니다. 고유 인덱스가 하는 일입니다.

중복 값을 피하는 것은 논리적 또는 기술적 관점에서 데이터 무결성을 보장하는 데 필요한 경우가 많습니다. 예를 들어, 동일한 주민등록번호를 사용하는 두 명의 다른 사람이 있어서는 안 되며, 온라인 시스템에서 동일한 사용자 이름이나 이메일 주소를 가진 여러 사용자가 등록하는 것을 허용해서는 안 됩니다.

이 가이드의 employees 테이블 예제의 경우 할당된 장치의 일련 번호는 중복을 포함해서는 안 되는 필드입니다. 그렇다면 두 명의 직원에게 동일한 컴퓨터가 주어졌음을 의미합니다. 그러나 이 시점에서 일련 번호가 반복되는 새 직원을 쉽게 삽입할 수 있습니다.

이미 사용 중인 장치 일련 번호를 가진 다른 직원을 삽입해 보십시오.

  1. INSERT INTO employees VALUES (21, 'Sammy', 'Smith', 'ABC123', 65000);

데이터베이스는 행을 의무화하고 삽입하여 성공을 알려줍니다.

Output
Query OK, 1 row affected (0.009 sec)

그러나 이제 다음과 같이 ABCD123 컴퓨터를 사용하여 직원에 대한 데이터베이스를 쿼리하는 경우:

  1. SELECT * FROM employees WHERE device_serial = 'ABC123';

결과적으로 두 명의 다른 사람을 얻게 됩니다.

Output
+-------------+------------+-----------+---------------+--------+ | employee_id | first_name | last_name | device_serial | salary | +-------------+------------+-----------+---------------+--------+ | 1 | John | Smith | ABC123 | 60000 | | 21 | Sammy | Smith | ABC123 | 65000 | +-------------+------------+-----------+---------------+--------+ 2 rows in set (0.000 sec)

이는 직원 데이터베이스를 유효하게 유지하기 위해 예상되는 동작이 아닙니다. 새로 생성된 행을 삭제하여 이 변경 사항을 되돌리겠습니다.

  1. DELETE FROM employees WHERE employee_id = 21;

이전 SELECT 쿼리를 다시 실행하여 확인할 수 있습니다.

  1. SELECT * FROM employees WHERE device_serial = 'ABC123';

다시 한 번 John Smith만이 일련 번호가 ABC123인 기기를 사용합니다.

Output
+-------------+------------+-----------+---------------+--------+ | employee_id | first_name | last_name | device_serial | salary | +-------------+------------+-----------+---------------+--------+ | 1 | John | Smith | ABC123 | 60000 | +-------------+------------+-----------+---------------+--------+ 1 row in set (0.000 sec)

이러한 실수로부터 데이터베이스를 보호하기 위해 device_serial 열에 고유 인덱스를 생성할 수 있습니다.

이렇게 하려면 다음을 실행합니다.

  1. CREATE UNIQUE INDEX device_serial ON employees(device_serial);

인덱스를 생성할 때 UNIQUE 키워드를 추가하면 device_serial 열의 값이 반복되지 않도록 데이터베이스에 지시합니다. 고유 인덱스를 사용하면 테이블에 추가된 모든 새 행을 인덱스에 대해 검사하여 열 값이 제약 조건을 충족하는지 여부를 확인합니다.

데이터베이스는 색인 생성을 확인합니다.

Output
Query OK, 0 rows affected (0.021 sec) Records: 0 Duplicates: 0 Warnings: 0

이제 테이블에 중복 항목을 추가할 수 있는지 확인하십시오. 이전에 성공한 INSERT 쿼리를 다시 실행해 보십시오.

  1. INSERT INTO employees VALUES (21, 'Sammy', 'Smith', 'ABC123', 65000);

이번에는 오류 메시지가 표시됩니다.

Output
ERROR 1062 (23000): Duplicate entry 'ABC123' for key 'device_serial'

SELECT 쿼리를 다시 사용하여 새 행이 테이블에 추가되지 않았는지 확인할 수 있습니다.

  1. SELECT * FROM employees WHERE device_serial = 'ABC123';

이제 단일 행이 반환됩니다.

Output
+-------------+------------+-----------+---------------+--------+ | employee_id | first_name | last_name | device_serial | salary | +-------------+------------+-----------+---------------+--------+ | 1 | John | Smith | ABC123 | 60000 | +-------------+------------+-----------+---------------+--------+ 1 row in set (0.000 sec)

고유 인덱스는 중복 항목으로부터 보호하는 것 외에도 쿼리 속도를 높이기 위한 완전한 기능의 인덱스입니다. 데이터베이스 엔진은 이전 단계와 동일한 방식으로 고유 인덱스를 사용합니다. 다음을 실행하여 이를 확인할 수 있습니다.

  1. EXPLAIN SELECT * FROM employees WHERE device_serial = 'ABC123';

실행 계획은 다음과 유사합니다(표는 약간 다를 수 있음).

Output
+----+-------------+-----------+------------+-------+---------------+---------------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+-------+---------------+---------------+---------+-------+------+----------+-------+ | 1 | SIMPLE | employees | NULL | const | device_serial | device_serial | 63 | const | 1 | 100.00 | NULL | +----+-------------+-----------+------------+-------+---------------+---------------+---------+-------+------+----------+-------+ 1 row in set, 1 warning (0.00 sec)

device_serial 인덱스는 possible_keyskey 열 모두에 표시되어 쿼리를 수행할 때 인덱스가 사용되었음을 확인합니다.

고유 인덱스를 사용하여 데이터베이스의 중복 데이터를 방지했습니다. 다음 섹션에서는 둘 이상의 열에 걸쳐 있는 인덱스를 사용합니다.

여러 열에서 인덱스 사용

지금까지 이전 섹션에서 만든 모든 인덱스는 선택한 열의 값과 관련된 단일 열 이름을 사용하여 정의되었습니다. 대부분의 데이터베이스 시스템은 둘 이상의 열에 걸쳐 있는 인덱스를 지원합니다. 다중 열 인덱스라고 하는 이러한 인덱스는 단일 인덱스에 여러 열의 값을 저장하는 방법을 제공하므로 데이터베이스 엔진이 열 집합을 함께 사용하여 쿼리를 보다 빠르고 효율적으로 실행할 수 있습니다.

성능을 위해 최적화되어야 하는 자주 사용되는 쿼리는 종종 WHERE 필터링 절에서 여러 조건을 사용합니다. 이러한 종류의 쿼리의 예는 이름과 성을 모두 사용하여 사람을 찾도록 데이터베이스에 요청하는 것입니다.

  1. SELECT * FROM employees WHERE last_name = 'Smith' AND first_name = 'John';

인덱스를 사용하여 이 쿼리를 최적화하는 첫 번째 생각은 last_name 열과 first_name 열에 하나씩 두 개의 개별 인덱스를 만드는 것입니다. 그러나 이것은 이 상황에서 최선의 선택이 아닙니다.

이러한 방식으로 두 개의 개별 인덱스를 생성한 경우 MySQL은 Smith라는 이름의 모든 직원을 찾는 방법을 알고 있을 것입니다. 또한 John이라는 이름의 모든 직원을 찾는 방법도 알고 있습니다. 그러나 이름이 John Smith인 사람을 찾는 방법은 알 수 없습니다.

두 개의 개별 색인이 있는 문제를 설명하기 위해 하나는 성과 이름으로 정렬된 두 개의 개별 전화번호부가 있다고 상상해 보십시오. 두 전화번호부는 각각 last_namefirst_name 열에 생성된 인덱스와 유사합니다. 전화번호부 사용자는 다음 세 가지 방법으로 John Smith를 찾는 문제에 접근할 수 있습니다.

  • 성을 기준으로 정렬된 전화번호부를 사용하여 Smith라는 이름을 가진 모든 사람을 찾고, 두 번째 전화번호부는 무시하고 찾을 때까지 모든 Smith 사람을 수동으로 하나씩 이동합니다. 존 스미스.
  • 반대 작업: 이름순으로 정렬된 전화번호부를 사용하여 John이라는 이름의 모든 사람을 찾고, 두 번째 전화번호부는 무시하고 모든 John 사람을 수동으로 하나씩 탐색합니다. John Smith를 찾을 때까지 하나.
  • 두 전화번호부를 함께 사용하려고 합니다. John이라는 이름의 모든 사람과 Smith라는 이름의 모든 사람을 개별적으로 찾아서 중간 결과를 기록한 다음 두 사람을 수동으로 교차시킵니다. 두 개별 목록에 있는 사람을 찾는 데이터의 하위 집합입니다.

이러한 접근 방식 중 어느 것도 이상적이지 않으며 MySQL은 여러 개의 분리된 인덱스와 둘 이상의 필터링 조건을 요구하는 쿼리를 처리할 때 유사한 선택을 할 수 있습니다.

또 다른 접근 방식은 단일 열이 아닌 여러 열을 고려하는 인덱스를 사용하는 것입니다. 이것을 다른 전화번호부 안에 있는 전화번호부라고 상상할 수 있습니다. 먼저 Smith라는 성을 검색하면 Smith라는 이름의 모든 사람들이 조직된 두 번째 카탈로그로 연결됩니다. John을 빠르게 찾는 데 사용할 수 있는 이름의 알파벳순.

참고: MySQL은 쿼리에 사용되는 각 테이블에 대해 하나의 인덱스만 사용할 수 있다고 종종 말합니다. MySQL은 쿼리를 실행할 때 여러 인덱스를 공동으로 사용하도록 인덱스 병합 최적화를 지원하므로 항상 그런 것은 아닙니다. 그러나 이 제한은 인덱스를 작성할 때 좋은 경험 법칙입니다. MySQL은 여러 인덱스를 사용하지 않기로 결정할 수 있습니다. 그렇더라도 많은 시나리오에서 목적과 전용 인덱스를 제공하지 않습니다.

MySQL에서 employees 테이블의 성 및 이름에 대한 다중 열 인덱스를 생성하려면 다음을 실행합니다.

  1. CREATE INDEX names ON employees(last_name, first_name);

이 경우 CREATE INDEX 문은 약간 다릅니다. 이제 테이블 이름(employees) 뒤의 괄호 안에 last_namefirst_name의 두 열이 나열됩니다. 이렇게 하면 두 열 모두에 다중 열 인덱스가 생성됩니다. 곧 알게 되겠지만 인덱스 정의에 열이 나열되는 순서는 중요합니다.

데이터베이스는 인덱스가 성공적으로 생성되었음을 확인하는 다음 메시지를 표시합니다.

Output
Query OK, 0 rows affected (0.024 sec) Records: 0 Duplicates: 0 Warnings: 0

이제 SELECT 쿼리를 실행하여 이름이 John과 일치하고 성이 Smith와 일치하는 행을 찾으십시오.

  1. SELECT * FROM employees WHERE last_name = 'Smith' AND first_name = 'John';

결과는 John Smith라는 직원이 있는 단일 행입니다.

Output
+-------------+------------+-----------+---------------+--------+ | employee_id | first_name | last_name | device_serial | salary | +-------------+------------+-----------+---------------+--------+ | 1 | John | Smith | ABC123 | 60000 | +-------------+------------+-----------+---------------+--------+ 1 row in set (0.000 sec)

이제 EXPLAIN 쿼리를 사용하여 인덱스가 사용되었는지 확인합니다.

  1. EXPLAIN SELECT * FROM employees WHERE last_name = 'Smith' AND first_name = 'John';

실행 계획은 다음과 유사합니다(표는 약간 다를 수 있음).

Output
+----+-------------+-----------+------------+------+---------------+-------+---------+-------------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+-------+---------+-------------+------+----------+-------+ | 1 | SIMPLE | employees | NULL | ref | names | names | 406 | const,const | 1 | 100.00 | NULL | +----+-------------+-----------+------------+------+---------------+-------+---------+-------------+------+----------+-------+ 1 row in set, 1 warning (0.00 sec)

데이터베이스는 names 색인을 사용했습니다. 단일 행이 스캔되었으므로 테이블이 필요 이상으로 트래버스되지 않았습니다. Extra 열에는 인덱스 조건 사용이 표시되며 이는 MySQL이 인덱스만을 사용하여 필터링을 완료할 수 있음을 의미합니다.

이 두 열에 걸쳐 있는 다중 열 인덱스를 사용하여 이름과 성을 필터링하면 데이터베이스에서 원하는 결과를 직접적이고 빠르게 찾을 수 있습니다.

두 열에 정의된 인덱스를 사용하여 이름이 Smith인 모든 직원을 찾으려고 하지만 이름에 대해 필터링하지 않으면 어떻게 됩니까? 수정된 쿼리를 실행합니다.

  1. SELECT * FROM employees WHERE last_name = 'Smith';

출력은 다음을 반환합니다.

Output
+-------------+------------+-----------+---------------+--------+ | employee_id | first_name | last_name | device_serial | salary | +-------------+------------+-----------+---------------+--------+ | 20 | Abigail | Smith | FGH890 | 155000 | | 17 | Daniel | Smith | WXY901 | 140000 | | 1 | John | Smith | ABC123 | 60000 | | 5 | Michael | Smith | MNO345 | 80000 | +-------------+------------+-----------+---------------+--------+ 4 rows in set (0.000 sec)

4명의 직원은 성이 Smith입니다.

다시 한 번 쿼리 실행 계획에 액세스합니다.

  1. EXPLAIN SELECT * FROM employees WHERE last_name = 'Smith';

실행 계획은 다음과 유사합니다(표는 약간 다를 수 있음).

Output
+----+-------------+-----------+------------+------+---------------+-------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+-------+---------+-------+------+----------+-------+ | 1 | SIMPLE | employees | NULL | ref | names | names | 203 | const | 4 | 100.00 | NULL | +----+-------------+-----------+------------+------+---------------+-------+---------+-------+------+----------+-------+ 1 row in set, 1 warning (0.01 sec)

이번에는 해당 성을 가진 직원이 둘 이상이므로 4개의 행이 반환되었습니다. 그러나 실행 계획 테이블은 데이터베이스가 다중 열 인덱스 names를 사용하여 이 쿼리를 수행하고 반환된 정확한 수인 4 행만 스캔했음을 보여줍니다.

이전 쿼리에서 결과를 필터링하는 데 사용된 열(last_name)은 CREATE INDEX 문에서 첫 번째로 전달되었습니다. 이제 이 다중 열 인덱스에 대한 열 목록의 두 번째 열인 first_name으로 employees 테이블을 필터링합니다. 다음 쿼리를 실행합니다.

  1. SELECT * FROM employees WHERE first_name = 'John';

출력은 다음과 같이 반환됩니다.

Output
+-------------+------------+-----------+---------------+--------+ | employee_id | first_name | last_name | device_serial | salary | +-------------+------------+-----------+---------------+--------+ | 1 | John | Smith | ABC123 | 60000 | +-------------+------------+-----------+---------------+--------+ 1 row in set (0.000 sec)

쿼리 실행 계획에 액세스합니다.

  1. EXPLAIN SELECT * FROM employees WHERE first_name = 'John';

출력은 다음과 같이 반환됩니다.

Output
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | employees | NULL | ALL | NULL | NULL | NULL | NULL | 20 | 10.00 | Using where | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec)

다시 한 번 반환된 결과에는 단일 직원이 포함되지만 이번에는 인덱스가 사용되지 않았습니다. 데이터베이스는 Extra 열의 Using where 주석과 20 스캔된 행으로 표시된 전체 테이블을 스캔했습니다.

이 경우 인덱스가 처음 생성될 때 CREATE INDEX 문에 전달된 열의 순서(last_name, first_name) 때문에 데이터베이스가 인덱스를 사용하지 않았습니다. 데이터베이스는 쿼리가 첫 번째 열 또는 첫 번째 열과 두 번째 열을 모두 사용하는 경우에만 인덱스를 사용할 수 있습니다. 인덱스 정의의 첫 번째 열이 사용되지 않는 인덱스에 대한 쿼리를 지원할 수 없습니다.

여러 열에 생성된 인덱스를 통해 데이터베이스는 인덱스를 사용하여 모든 인덱싱된 열 또는 증가하는 모든 인덱싱된 열의 왼쪽 접두사와 관련된 쿼리 속도를 높일 수 있습니다. 예를 들어 (a, b, c) 열을 포함하는 다중 열 인덱스를 사용하여 세 열 모두와 관련된 쿼리와 처음 두 열만 관련된 쿼리의 속도를 높일 수 있습니다. 첫 번째 열만 포함하는 쿼리. 반면에 인덱스는 마지막 열 c 또는 마지막 두 열 bc 와 관련된 쿼리에는 도움이 되지 않습니다.

인덱스에 포함된 열과 순서를 신중하게 선택하면 단일 다중 열 인덱스를 사용하여 동일한 테이블에 대한 다양한 쿼리 속도를 높일 수 있습니다. 이 예에서 직원 조회가 이름과 성 둘 다 또는 성만으로 이루어진다고 가정하면 names 인덱스에 제공된 열 순서는 인덱스가 모든 관련 쿼리의 속도를 높이는 것을 보장합니다.

이 섹션에서는 다중 열 인덱스를 사용하고 이러한 인덱스를 지정할 때 열 순서에 대해 배웠습니다. 다음 섹션에서는 기존 인덱스를 관리하는 방법을 배웁니다.

기존 인덱스 나열 및 제거

이전 섹션에서는 새 인덱스를 만들었습니다. 인덱스에는 이름이 있고 특정 테이블에 정의되어 있으므로 인덱스를 나열하고 필요할 때 조작할 수도 있습니다.

employees 테이블에 대해 이 자습서에서 생성한 모든 인덱스를 나열하려면 다음 문을 실행합니다.

  1. SHOW INDEXES FROM employees;

출력은 다음과 유사합니다.

Output
+-----------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression | +-----------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | employees | 0 | device_serial | 1 | device_serial | A | 20 | NULL | NULL | YES | BTREE | | | YES | NULL | | employees | 1 | salary | 1 | salary | A | 20 | NULL | NULL | YES | BTREE | | | YES | NULL | | employees | 1 | names | 1 | last_name | A | 16 | NULL | NULL | YES | BTREE | | | YES | NULL | | employees | 1 | names | 2 | first_name | A | 20 | NULL | NULL | YES | BTREE | | | YES | NULL | +-----------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ 4 rows in set (0.01 sec)

MySQL 버전에 따라 출력이 약간 다를 수 있지만 이름, 인덱스를 정의하는 데 사용되는 열, 고유성에 대한 정보 및 인덱스 정의의 기타 광범위한 세부 정보를 포함한 모든 인덱스가 포함됩니다.

기존 인덱스를 삭제하려면 DROP INDEX SQL 문을 사용할 수 있습니다. 더 이상 device_serial 열에 고유성을 적용하고 싶지 않다고 상상해 보십시오. 따라서 device_serial 인덱스는 더 이상 필요하지 않습니다. 다음 명령을 실행합니다.

  1. DROP INDEX device_serial ON employees;

device_serial은 인덱스 이름이고 employees는 인덱스가 정의된 테이블입니다. 데이터베이스는 색인 삭제를 확인합니다.

Output
Query OK, 0 rows affected (0.018 sec) Records: 0 Duplicates: 0 Warnings: 0

때로는 일반적인 쿼리의 패턴이 시간이 지남에 따라 변경되거나 새로운 쿼리 유형이 두드러지게 됩니다. 그런 다음 사용된 인덱스를 재평가하거나, 새 인덱스를 생성하거나, 사용하지 않는 인덱스를 삭제하여 최신 상태로 유지하여 데이터베이스 성능 저하를 방지해야 할 수 있습니다.

DROP INDEX 명령을 사용하면 인덱스가 필요하고 유용할 때 인덱스를 만드는 모범 사례에 따라 기존 데이터베이스에서 인덱스를 관리할 수 있습니다.

결론

이 가이드를 따라 인덱스가 무엇이고 MySQL에서 가장 일반적인 유형을 사용하여 조건부 SELECT 쿼리를 통해 데이터 검색 속도를 높이는 방법을 배웠습니다. 인덱스를 사용하여 열 데이터 고유성을 유지하고 필터링 조건에서 둘 이상의 열이 사용되는 쿼리에 인덱스가 어떻게 영향을 미칠 수 있는지 배웠습니다.

인덱스를 사용하여 가장 자주 실행되는 쿼리 유형에 따라 데이터베이스의 성능을 형성하여 일반적인 사용 사례에 대한 읽기 및 쓰기 성능 간의 적절한 균형을 맞출 수 있습니다. 이 자습서에서는 해당 용도로 인덱스를 사용하는 기본 사항만 다루었습니다. MySQL이 사용할 인덱스를 선택하는 방법과 인덱스를 사용할 시기를 이해하면 인덱스를 통해 더 복잡한 쿼리를 지원할 수 있습니다. 이에 대한 자세한 내용은 인덱스에 대한 MySQL 설명서를 참조하십시오.

SQL 언어와 작업에 대한 다양한 개념에 대해 자세히 알아보려면 SQL 사용 방법 시리즈의 다른 가이드를 확인하는 것이 좋습니다.