MySQL 테이블에 인덱스를 어떻게 추가합니까?


407

약 150,000 행의 데이터가있는 매우 큰 MySQL 테이블이 있습니다. 현재 시도하고 실행할 때

SELECT * FROM table WHERE id = '1';

ID 필드가 기본 인덱스이므로 코드가 제대로 실행됩니다. 그러나 프로젝트의 최근 개발을 위해서는 다른 필드로 데이터베이스를 검색해야합니다. 예를 들면 다음과 같습니다.

SELECT * FROM table WHERE product_id = '1';

이 필드는 이전에 색인화되지 않았습니다. 그러나 하나를 추가 했으므로 mysql은 이제 필드를 색인화하지만 위 쿼리를 실행하려고하면 매우 느리게 실행됩니다. EXPLAIN 쿼리는 product_id 필드에 이미 인덱스를 추가했을 때 인덱스가 없다는 것을 나타내므로 쿼리는 단일 행을 반환하는 데 20 분에서 30 분이 걸립니다.

내 전체 EXPLAIN 결과는 다음과 같습니다.

| id | select_type | table | type | possible_keys| key  | key_len | ref  | rows  | Extra       |
+----+-------------+-------+------+--------------+------+---------+------+-------+------------------+
|  1 | SIMPLE      | table | ALL  | NULL         | NULL | NULL    | NULL |157211 | Using where |
+----+-------------+-------+------+--------------+------+---------+------+-------+------------------+

방금 살펴본 결과 ID 필드는 INT로 저장되고 PRODUCT_ID 필드는 VARCHAR로 저장됩니다. 이것이 문제의 원인 일 수 있습니까?


1
전체 EXPLAIN결과 를 게시 할 수 있습니까 ? 인덱스 가 없다는 것이 확실 합니까? 아니면 인덱스가 있습니까?하지만 MySQL이 사용하지 않기로 선택 했습니까?
VoteyDisciple

169
큰 테이블에는 150,000,000 개의 레코드가 있습니다. 매우 큰 테이블에는 15,000,000,000 개의 레코드가 있습니다. 평균 크기의 테이블은 150,000입니다. 나중에 참조하십시오.
usumoio

4
'OR'을 사용하면 MySql이 인덱스를 사용하지 않을 수 있습니다. OR이 3 개인 쿼리가있었습니다. 각각 인덱스를 생성하고 15ms 동안 실행했습니다. 모두 25 초에서 시간 초과되었습니다. 그래서 3 개의 쿼리를 작성하고 UNION을 함께 결합했으며 500.000 행에 15ms가 걸렸습니다.
Leif Neland

저장중인 데이터 유형을 고려하십시오. 비교하는 데이터 유형에 따라 성능이 변경 될 수 있습니다. PRODUCT_ID가 VARCHAR 데이터 유형이라고 말했듯이 INT로 변경하고 열을 색인화하십시오.
길버트

답변:


606
ALTER TABLE `table` ADD INDEX `product_id_index` (`product_id`)

절대 비교할 integerstrings있는 MySQL. 경우 id이며 int, 따옴표를 제거합니다.


정확한 SQL을 사용하여 인덱스를 이미 추가했지만 데이터에 "적용되지 않은"것 같으며 EXPLAIN 쿼리에 필드에 대한 인덱스가 없음이 표시됩니다.
Michael

1
SHOW CREATE TABLE을 사용하여 색인을 점검하거나 이미 수행 했습니까?
Wrikken

33
SHOW INDEXES FROM YOURTABLE dev.mysql.com/doc/refman/5.0/en/show-index.html 을 사용 하여 색인이 추가되었는지 확인하십시오.
Timo Huovinen

6
오늘 @Michael이 설명하는 정확한 문제가 있었으며 해결책은 "mysql의 정수와 문자열을 절대로 비교하지 마십시오."였습니다. 감사합니다.
user12345

@Wrikken 인덱스를 추가하고 SHOW INDEXES FROM YOURTABLE 명령을 사용했습니다. 표시되지만 테이블을 쿼리하는 동안 사용되지는 않습니다. 인덱스를 사용할 때 선택 쿼리를 변경해야합니까?
Ced

148
ALTER TABLE TABLE_NAME ADD INDEX (COLUMN_NAME);

97
MySQL의에서 사용할 경우 ALTER TABLE tbl ADD INDEX (col)대신 ALTER TABLE tbl ADD INDEX col (col)다음 사용하여 ALTER TABLE tbl ADD INDEX (col)명명 된 인덱스를 계속 추가 할 것이다 번 이상 col_2, col_3...마다. ALTER TABLE tbl ADD INDEX col (col)두 번째 시간을 사용하는 대신을 제공 ERROR 1061 (42000): Duplicate key name 'col'합니다.
Abhishek Oza

82

이 구문을 사용하여 색인을 추가하고 색인 종류 (HASH 또는 BTREE)를 제어 할 수 있습니다.

create index your_index_name on your_table_name(your_column_name) using HASH;
or
create index your_index_name on your_table_name(your_column_name) using BTREE;

BTREE와 HASH 인덱스의 차이점에 대해서는 http://dev.mysql.com/doc/refman/5.5/en/index-btree-hash.html에서 확인할 수 있습니다.


1
show 인덱스 사용을 볼 때 해시가 btree로 변환되었습니다.
RN Kushwaha

1
지정하지 않으면 Hash 및 BTree의 기본값은 무엇입니까?
Bhavuk Mathur

2
InnoDB와 MyIsam은 HASH, AFAIK를 지원하지 않기 때문에 @RNKushwaha, 메모리 및 NDB 스토리지 엔진 만 지원
Hieu Vo

60

여러 개의 필드 인덱스를 사용하면 쿼리 성능이 크게 향상 될 수 있습니다. 위의 예에서 ProductID가 조회 할 유일한 필드이지만 ProductID = 1 AND Category = 7이라고하는 쿼리 인 경우 다중 열 인덱스가 도움이됩니다. 이것은 다음과 같이 달성됩니다.

ALTER TABLE `table` ADD INDEX `index_name` (`col1`,`col2`)

또한 인덱스는 쿼리 필드의 순서와 일치해야합니다. 확장 된 예제에서 색인은 (ProductID, Category)가 아니면 안됩니다.


1
인덱스의 이름을 명확하게 지정하면 쉽게 되돌릴 수 있습니다.
Sam Berry

의 출처를 인용 할 수 있습니까 the index should match the order of the query fields?
Bishwas Mishra

58

두 가지 유형의 인덱스를 추가 할 수 있습니다. 기본 키를 정의하면 MySQL이 기본적으로 인덱스를 인덱스로 사용합니다.

설명

인덱스로 기본 키

당신이이 고려 tbl_student테이블을하고 당신이 원하는 student_id기본 키로 :

ALTER TABLE `tbl_student` ADD PRIMARY KEY (`student_id`)

위의 명령문은 기본 키를 추가합니다. 즉, 색인화 된 값은 고유해야하며 NULL 일 수 없습니다.

색인 이름을 지정하십시오

ALTER TABLE `tbl_student` ADD INDEX student_index (`student_id`)

위의 문장은 student_index이름으로 일반 색인을 만듭니다 .

고유 인덱스 생성

ALTER TABLE `tbl_student` ADD UNIQUE student_unique_index (`student_id`)

여기, student_unique_indexstudent_id에 할당 된 색인 이름이며 값이 고유해야하는 색인을 작성합니다 (여기서는 널을 허용 할 수 있음).

전체 텍스트 옵션

ALTER TABLE `tbl_student` ADD FULLTEXT student_fulltext_index (`student_id`)

위의 문장은 student_fulltext_indexMyISAM Mysql Engine이 필요한 전체 텍스트 인덱스 이름을로 만듭니다 .

인덱스를 제거하는 방법?

DROP INDEX `student_index` ON `tbl_student`

사용 가능한 인덱스를 확인하는 방법은 무엇입니까?

SHOW INDEX FROM `tbl_student`

17

당신은 당신이 색인이 있다고 말하면, 설명은 그렇지 않다고 말합니다. 그러나 실제로 할 경우 다음과 같이 진행하십시오.

열에 인덱스가 있고 MySQL이 사용하지 않기로 결정한 경우 다음과 같은 이유로 인해 인덱스가 발생할 수 있습니다.

  1. 쿼리에 MySQL이 사용하기에 더 적합한 것으로 간주되는 또 다른 인덱스가 있으며 하나만 사용할 수 있습니다. 일반적인 검색 방법이 둘 이상의 열 값인 경우 솔루션은 일반적으로 여러 열에 걸친 인덱스입니다.
  2. MySQL은 많은 일치하는 행이 있다고 결정하고 테이블 스캔이 더 빠를 것이라고 생각합니다. 그렇지 않은 경우에는 때때로 ANALYZE TABLE도움이됩니다.
  3. 보다 복잡한 쿼리에서는 쿼리 계획에서 매우 지능적인 사고 부두를 기반으로 사용하지 않기로 결정합니다. 어떤 이유로 든 현재 요구 사항에 맞지 않습니다.

(2) 또는 (3)의 경우 인덱스 힌트 sytax인덱스 를 사용하도록 MySQL을 동축시킬 수 있지만, 그렇게 할 경우 실제로 테스트 할 때 인덱스를 사용하는 것이 실제로 성능을 향상시키는 지 확인하기 위해 테스트를 실행하십시오. .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.