MySQL 인덱스-모범 사례는 무엇입니까?


208

나는 지금까지 MySQL 데이터베이스에서 인덱스를 사용해 왔지만 그것에 대해 제대로 배우지 못했습니다 . 일반적으로 WHERE절을 사용하여 검색하거나 선택할 필드에 색인을 넣지 만 때로는 흑백으로 보이지 않는 경우가 있습니다.

MySQL 인덱스에 대한 모범 사례는 무엇입니까?

상황 / 딜레마 예 :

  • 테이블에 6 개의 열이 있고 모두 열을 검색 할 수 있으면 열을 모두 색인화해야합니까 아니면 전혀 색인화하지 않아야합니까?

  • 인덱싱의 부정적인 성능 영향은 무엇입니까?

  • 내 사이트의 일부에서 검색 할 수있는 VARCHAR 2500 열이있는 경우 색인을 작성해야합니까?


5
질문에 태그를 다시 지정해야합니다. 인덱스 선택은 모든 데이터베이스 모델을 최적화하는 데 중요한 부분입니다. 그리고 내 견해로는 PHP와 관련이 없습니다.
VGE


답변:


242

인덱싱에 대해 읽는 데 시간을 투자해야하며 그것에 대해 많은 글이 있으며 무슨 일이 일어나고 있는지 이해하는 것이 중요합니다.

대체로 인덱스는 테이블의 행에 순서를 부과합니다.

간단히하기 위해 테이블이 큰 CSV 파일이라고 가정 해보십시오. 행이 삽입 될 때마다 끝에 삽입 됩니다 . 따라서 테이블의 "자연스러운"순서는 행이 삽입 된 순서입니다.

매우 기본적인 스프레드 시트 응용 프로그램에 CSV 파일이로드되었다고 가정합니다. 이 스프레드 시트는 데이터를 표시하고 행에 순차적으로 번호를 매 깁니다.

이제 세 번째 열에서 "M"값을 가진 모든 행을 찾아야한다고 상상해보십시오. 사용 가능한 것을 감안할 때 하나의 옵션 만 있습니다. 각 행의 세 번째 열 값을 확인하여 테이블을 스캔합니다. 많은 행이있는 경우이 방법 ( "테이블 스캔")에 시간이 오래 걸릴 수 있습니다!

이제이 표 외에 색인이 있다고 가정하십시오. 이 특정 인덱스는 세 번째 열의 값 인덱스입니다. 색인은 세 번째 열의 모든 값을 의미있는 순서 (알파벳순)로 나열하고 각각에 대해 해당 값이 나타나는 행 번호 목록을 제공합니다.

이제 세 번째 열의 값이 "M"인 모든 행을 찾는 좋은 전략이 있습니다. 예를 들어 이진 검색을 수행 할 수 있습니다 ! 테이블 스캔에서는 N 개의 행을보아야하지만 (여기서 N은 행 수임) 바이너리 검색에서는 최악의 경우 log-n 인덱스 항목 만보아야합니다. 와우, 훨씬 쉬워요!

물론이 인덱스가 있고 테이블에 행을 추가하는 경우 (결국 개념 테이블이 작동하는 방식이므로) 인덱스를 매번 업데이트해야합니다. 따라서 새로운 행을 작성하는 동안 약간의 작업을 수행하지만 무언가를 검색 할 때 시간을 절약 할 수 있습니다.

따라서 일반적으로 인덱싱은 읽기 효율성과 쓰기 효율성 간의 균형을 유지합니다. 인덱스가 없으면 삽입 속도가 매우 빠를 수 있습니다. 데이터베이스 엔진은 테이블에 행을 추가하기 만합니다. 색인을 추가 할 때 엔진은 삽입을 수행하는 동안 각 색인을 업데이트해야합니다.

반면에 읽기는 훨씬 빨라집니다.

바라건대 첫 두 질문 (다른 사람들이 대답했듯이 올바른 균형을 찾아야 함)을 다루기를 바랍니다.

세 번째 시나리오는 조금 더 복잡합니다. LIKE를 사용하는 경우 인덱싱 엔진은 일반적으로 첫 번째 "%"까지 읽기 속도를 도와줍니다. 즉, 'foo % bar %'와 같은 열을 선택하는 경우 데이터베이스는 색인을 사용하여 열이 "foo"로 시작하는 모든 행을 찾은 다음 해당 하위 행 세트를 스캔하여 서브 세트를 찾습니다. "바"를 포함합니다. SELECT ... WHERE 열 LIKE '% bar %'은 (는) 인덱스를 사용할 수 없습니다. 왜 그런지 알 수 있기를 바랍니다.

마지막으로 두 개 이상의 열에서 인덱스에 대해 생각해야합니다. 개념은 동일하며 LIKE와 유사하게 작동합니다. 기본적으로 (a, b, c)에 색인이 있으면 엔진은 가능한 한 왼쪽에서 오른쪽으로 색인을 계속 사용합니다. 따라서 열 a에서 검색 할 때 (a, b)에서와 같이 (a, b, c) 색인을 사용할 수 있습니다. 그러나 b = 5 AND c = 1 인 곳을 검색하는 경우 엔진에서 전체 테이블 스캔을 수행해야합니다.

이 방법이 약간 도움이 되길 바랍니다. 그러나 이러한 내용을 자세히 설명하는 좋은 기사를 찾기 위해 몇 시간을 투자하는 것이 가장 좋습니다. 특정 데이터베이스 서버의 설명서를 읽는 것도 좋습니다. 쿼리 플래너가 인덱스를 구현하고 사용하는 방법은 매우 다양 할 수 있습니다.


10
무엇에 대한 FULLTEXT인덱스? 그들은 같은 조건을 도울 수 있습니까 LIKE '%bar%'?
Septagram

2
@Septagram- "단어"인 경우 해당 쿼리를 FULLTEXT도울 수 있습니다 . 임의의 하위 문자열이 아닌 단어를 처리합니다 (있는 것처럼 ). barFULLTEXTLIKE
Rick James

@timdev는 어느 부분에서 첫 번째 질문에 명시 적으로 대답 했습니까? 귀중한 답변 의 첫 번째와 두 번째 부분 ( 첫 번째 두 가지 질문을 다루는 이전과 이후)에서 답변 된 두 번째와 세 번째 질문을 발견 할 수 있습니다.
Manuel Jordan

1
@ManuelJordan-첫 번째 질문에 대한 간단한 답변이 없습니다. 예상되는 (또는 더 나은 관찰 된) 사용량과 관련하여 트레이드 오프의 균형을 맞추려는 방법에 따라 다릅니다.
timdev 2009 년

57

인덱싱 기술 더 마스터 링 과 같은 프레젠테이션을 확인하십시오 .

2012 년 12 월 12 일 업데이트 : 인덱스를 디자인하는 방법 에 대한 새로운 프레젠테이션을 게시했습니다 . 2012 년 10 월 산타 클라라의 젠드 콘에서, 2012 년 12 월에는 퍼 코나 라이브 런던에서 이것을 발표했습니다.

최상의 인덱스를 디자인하는 것은 앱에서 실행하는 쿼리와 일치해야하는 프로세스입니다.

어떤 열을 가장 잘 인덱싱해야하는지 또는 모든 열을 인덱싱해야하는지, 여러 열에 걸쳐 있어야하는 인덱스 등을 지정해야하는지에 대한 일반적인 규칙은 권장하기가 어렵습니다. 실행해야하는 쿼리에 따라 다릅니다.

예, 약간의 오버 헤드가 있으므로 불필요하게 인덱스를 생성하지 않아야합니다. 하지만 당신은 해야 빠르게 실행하는 데 필요한 쿼리에 혜택을주는 인덱스를 만들 수 있습니다. 지수의 오버 헤드는 일반적으로 그 이점보다 훨씬 중요합니다.

VARCHAR (2500) 인 열의 경우 FULLTEXT 색인 또는 두부 색인 을 사용하려고합니다 .

CREATE INDEX i ON SomeTable(longVarchar(100));

긴 varchar의 중간에있을 수있는 단어를 검색하는 경우 기존 색인이 도움이되지 않습니다. 이를 위해 전체 텍스트 색인을 사용하십시오.


3
정말 고맙습니다. slideshare.net/matsunobu/… 정말 도움이되었습니다.
Bishal Paudel



1
놀라운 발표 (2012 년 발표)는 인덱스의 요점을 실제로 이해했습니다.
DarkteK

46

다른 답변에서 좋은 조언을 반복하지는 않지만 다음을 추가합니다.

복합 지수

복합 인덱스 (여러 열을 포함하는 인덱스)를 만들 수 있습니다. MySQL은 이것을 왼쪽 에서 오른쪽으로 사용할 수 있습니다 . 당신이 가지고 있다면 :

Table A
Id
Name
Category
Age
Description

Name / Category / Age를 순서대로 포함하는 복합 색인이있는 경우이 WHERE 절은 색인을 사용합니다.

WHERE Name='Eric' and Category='A'

WHERE Name='Eric' and Category='A' and Age > 18

그러나

WHERE Category='A' and Age > 18

모든 것을 왼쪽에서 오른쪽으로 사용해야하기 때문에 해당 인덱스를 사용하지 않습니다.

설명

Explain / Explain Extended를 사용하여 MySQL에서 사용할 수있는 인덱스와 실제로 선택하는 인덱스를 이해하십시오. MySQL은 쿼리 당 하나의 키만 사용 합니다 .

EXPLAIN EXTENDED SELECT * from Table WHERE Something='ABC'

느린 쿼리 로그

느린 쿼리 로그 를 켜서 실행중인 쿼리를 확인하십시오.

넓은 열

처음 몇 문자에서 구별이 가장 많이 발생하는 넓은 열이있는 경우 색인에서 처음 N 문자 만 사용할 수 있습니다. 예 : varchar (255)로 정의 된 ReferenceNumber 열이 있지만 사례의 97 %이며 참조 번호는 10 자 이하 여야합니다. 처음 10자를 보도록 색인을 변경하고 성능을 약간 향상 시켰습니다.


마지막 부분에 대한 질문이 있습니다. VARCHAR을 사용하여 열을 만들면 항상 255로 설정해야한다고 어딘가 읽었습니다. 이제이 유형의 열로 설정된 인덱스는 처음 10 자만 보도록 제한 할 수 있다고 말했습니다. 정확히 어떻게 할 수 있습니까?
AlexioVay

20

테이블에 6 개의 열이 있고 모든 열을 검색 할 수있는 경우 모두 색인을 작성해야합니까 아니면 전혀 색인을 작성하지 않아야합니까

필드를 기준으로 검색합니까, 아니면 여러 필드를 사용하는 검색입니까? 가장 많이 검색 되는 필드는 무엇입니까? 필드 유형은 무엇입니까? (예를 들어 인덱스는 VARCHAR보다 INT에서 더 잘 작동합니다.) 실행중인 쿼리에 EXPLAIN을 사용해 보셨습니까?

인덱싱의 성능에 미치는 부정적인 영향은 무엇입니까

업데이트 및 삽입 속도가 느려집니다. 추가 저장 공간 요구 사항도 있지만 요즘에는 일반적으로 중요하지 않습니다.

내 사이트의 일부에서 검색 할 수있는 VARCHAR 2500 열이있는 경우 색인을 작성해야합니까

아니요, UNIQUE (이미 색인화되어 있음)이거나 해당 필드 에서 정확히 일치하는 항목 만 검색 하지 않는 한 (LIKE 또는 mySQL의 전체 텍스트 검색을 사용하지 않음).

일반적으로 WHERE 절을 사용하여 검색하거나 선택할 필드에 색인을 넣습니다.

일반적으로 가장 많이 쿼리 된 필드를 인덱싱 한 다음 VARCHARS 인 필드 대신 INT / BOOLEANs / ENUM을 인덱싱합니다. 잊지 말고 종종 개별 필드에 대한 인덱스가 아니라 결합 된 필드에 대한 인덱스를 만들어야합니다. EXPLAIN을 사용하고 느린 로그를 확인하십시오.


11

효율적으로 데이터로드 : 인덱스를 사용하면 검색 속도는 빨라지지만 삽입 및 삭제 속도는 느려지고 인덱스 된 열의 값은 업데이트됩니다. 즉, 인덱스는 쓰기와 관련된 대부분의 작업을 느리게합니다. 이것은 행을 작성하는 데 데이터 행뿐만 아니라 색인도 변경해야하기 때문에 발생합니다. 테이블에 더 많은 인덱스가있을수록 더 많은 변경이 필요하며 평균 성능이 저하됩니다. 대부분의 테이블은 많은 읽기와 쓰기를 받지만 쓰기 비율이 높은 테이블의 경우 인덱스 업데이트 비용이 상당 할 수 있습니다.

색인 방지 : 쿼리의 성능을 향상시키기 위해 특정 색인이 필요하지 않은 경우 색인을 작성하지 마십시오.

디스크 공간 : 인덱스는 디스크 공간을 차지하고 여러 인덱스는 그에 따라 더 많은 공간을 차지합니다. 인덱스가없는 경우보다 테이블 크기 제한에 더 빨리 도달 할 수 있습니다. 가능하면 색인을 피하십시오.

테이크 아웃 : 인덱스를 초과하지 마십시오


5

일반적으로 인덱스는 별도의 디스크 공간을 사용하고 둔화의 단점 가지고, 속도 향상 데이터베이스 검색을 도와 INSERT/ UPDATE/ DELETE쿼리를. EXPLAINMySQL이 인덱스를 사용하는시기를 확인하려면 결과를 사용 하고 읽으십시오.

테이블에 6 개의 열이 있고 모두 열을 검색 할 수 있으면 열을 모두 색인화해야합니까 아니면 전혀 색인화하지 않아야합니까?

6 개의 열을 모두 인덱싱하는 것이 항상 최선의 방법은 아닙니다.

(a) 특정 정보를 검색 할 때 해당 열을 사용 하시겠습니까?

(ᄂ) 열의 선택성은 무엇입니까 (테이블의 총 레코드 수와 비교하여 몇 개의 고유 값이 저장되어 있습니까)?

MySQL은 비용 기반 옵티 마이저를 사용하여 쿼리를 수행 할 때 "가장 빠른"경로를 찾습니다. 그리고 선택성이 낮은 필드는 좋은 후보가 아닙니다.

인덱싱의 성능에 미치는 부정적인 영향은 무엇입니까?

이미 답변 : 추가 디스크 공간, 삽입 중 업데이트 성능 저하-삭제.

내 사이트의 일부에서 검색 할 수있는 VARCHAR 2500 열이있는 경우 색인을 작성해야합니까?

FULLTEXT 색인을 사용해보십시오 .


4

1/2) 인덱스는 특정 선택 작업을 가속화하지만 삽입, 업데이트 및 삭제와 같은 다른 작업을 느리게합니다. 균형이 잘 잡힐 수 있습니다.

3) 전체 텍스트 색인 또는 스핑크스 사용


방지하기 위해 slow down other operations like insert, update and deletes사용할 수있는 START TRANSACTION; YOUR CODE HERE; COMMIT 방지하는 데 도움이 될 수 있습니다 어떤 slowing down이 하나 하나 시간을 점검 제한 조건 바와 같이, 다른 작업을. 주의 : 당신이 사용하는 경우 REPLACE INTOSQL_MODE<> STRICT_ALL_TABLES또는 무시됩니다에 중복 삽입 교체합니다. TRADITIONALBulk Load
JayRizzo

일부 MySQL 엔진에서는 트랜잭션이 지원되지 않습니다. AFAIK에서 트랜잭션은 암시 적으로 만 사용하더라도 DB 작업 속도가 느려집니다. 실제 성능을 기반으로 디자인해야하는 것은 인덱스 및 트랜잭션을 포함하여 다양한 최적화 선택을 프로파일 링 (성능 측정)하는 반자동 방식입니다.
David Spector
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.