MySQL 인덱스의 작동 방식, 특히 전체 테이블을 스캔하지 않고 요청 된 데이터를 어떻게 반환 할 수 있습니까?
주제가 맞지 않습니다. 그러나 이것을 자세히 설명 할 수있는 사람이 있다면 매우 감사 할 것입니다.
SELECT * FROM members WHERE id = '1'
왜 인덱스를 사용하면 더 빨리 작동합니까? 그 인덱스는 무엇입니까?
MySQL 인덱스의 작동 방식, 특히 전체 테이블을 스캔하지 않고 요청 된 데이터를 어떻게 반환 할 수 있습니까?
주제가 맞지 않습니다. 그러나 이것을 자세히 설명 할 수있는 사람이 있다면 매우 감사 할 것입니다.
SELECT * FROM members WHERE id = '1'
왜 인덱스를 사용하면 더 빨리 작동합니까? 그 인덱스는 무엇입니까?
답변:
기본적으로 테이블의 인덱스는 책의 인덱스와 같이 작동합니다 (이름이 나온 곳).
데이터베이스에 관한 책이 있고 스토리지에 대한 정보를 찾고 싶다고 가정 해 봅시다. 색인이 없으면 (목차와 같은 다른 보조 도구가 없다고 가정 할 때) 주제를 찾을 때까지 (즉, full table scan
) 페이지를 하나씩 살펴 봐야합니다 . 반면에 색인에는 키워드 목록이 있으므로 색인을 참조하여storage
113-120,231 및 354 페이지에 나와있는 그런 다음 검색하지 않고 해당 페이지로 직접 넘길 수 있습니다 (즉, 색인, 다소 빠름).
물론 인덱스가 얼마나 유용한지는 위의 비유를 사용하여 몇 가지 예에 따라 다릅니다.
가장 먼저 알아야 할 것은 인덱스가 원하는 결과를 얻기 위해 전체 테이블을 스캔하지 않는 방법이라는 것입니다.
다양한 종류의 인덱스가 있으며 스토리지 계층에서 구현되므로 인덱스간에 표준이 없으며 사용중인 스토리지 엔진에 따라 다릅니다.
InnoDB의 경우 가장 일반적인 인덱스 유형은 요소를 정렬 된 순서대로 저장하는 B + Tree 기반 인덱스입니다. 또한 인덱스 된 값을 얻기 위해 실제 테이블에 액세스 할 필요가 없으므로 쿼리 반환 속도가 빨라집니다.
이 인덱스 유형에 대한 "문제"는 인덱스를 사용하기 위해 가장 왼쪽의 값을 쿼리해야한다는 것입니다. 따라서 인덱스에 last_name 및 first_name과 같은 두 개의 열이있는 경우 이러한 필드를 쿼리하는 순서가 중요합니다 .
따라서 다음 표를 참고하십시오.
CREATE TABLE person (
last_name VARCHAR(50) NOT NULL,
first_name VARCHAR(50) NOT NULL,
INDEX (last_name, first_name)
);
이 쿼리는 인덱스를 활용합니다.
SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"
그러나 다음 중 하나는
SELECT last_name, first_name FROM person WHERE first_name = "Constantine"
당신이 쿼리하기 때문에 first_name
먼저 열을 하고 인덱스에서 가장 왼쪽 열이 아니기 때문입니다.
이 마지막 예는 훨씬 더 나쁩니다.
SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"
이제 인덱스에서 가장 오른쪽 필드의 가장 오른쪽 부분을 비교하고 있습니다.
불행히도 메모리 백엔드 만 지원하는 다른 인덱스 유형입니다. 그것은의 번개 빠르지 만 작업이 좋아하는 당신이 그것을 사용할 수 없음을 의미합니다 전체 조회에 대한 유용 >
, <
또는 LIKE
.
메모리 백엔드에서만 작동하므로 자주 사용하지 않을 것입니다. 내가 지금 생각할 수있는 주요 사례는 다른 선택의 결과 집합으로 메모리에 임시 테이블을 만들고 해시 인덱스를 사용 하여이 임시 테이블에서 다른 많은 선택을 수행하는 경우입니다.
큰 VARCHAR
필드 가있는 경우 B- 트리를 사용할 때 다른 열을 만들고 큰 값의 해시를 저장하여 해시 인덱스 사용을 "에뮬레이션"할 수 있습니다. 필드에 URL을 저장하고 있으며 값이 상당히 크다고 가정 해 봅시다. 또한 정수 필드를 생성 url_hash
하고 해시 함수 CRC32
또는 다른 해시 함수를 사용하여 URL을 삽입 할 때 해시 할 수 있습니다. 그런 다음이 값을 쿼리해야 할 때 다음과 같은 작업을 수행 할 수 있습니다.
SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");
위 예제의 문제점은 CRC32
함수가 아주 작은 해시를 생성하므로 해시 된 값에서 많은 충돌이 발생한다는 것입니다. 정확한 값이 필요한 경우 다음을 수행하여이 문제를 해결할 수 있습니다.
SELECT url FROM url_table
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";
충돌 횟수가 크더라도 반복되는 해시에 대한 두 번째 비교 (문자열 1) 만 수행 할 경우에도 여전히 해싱 할 가치가 있습니다.
불행히도이 기술을 사용하면 url
필드 를 비교하기 위해 여전히 테이블을 쳐야합니다 .
최적화에 대해 이야기하고 싶을 때마다 고려해야 할 몇 가지 사실 :
정수 비교는 문자열 비교보다 훨씬 빠릅니다. 의 해시 인덱스 에뮬레이션에 대한 예를 통해 설명 할 수 있습니다 InnoDB
.
프로세스에 단계를 추가하면 속도가 느려지지 않고 빨라질 수 있습니다. a SELECT
를 두 단계로 나눠서 최적화 하여 첫 번째 값을 새로 만든 인 메모리 테이블에 저장 한 다음이 두 번째 테이블에서 더 많은 쿼리를 실행할 수 있다는 사실을 알 수 있습니다 .
MySQL에는 다른 인덱스도 있지만 B + Tree는 가장 많이 사용되며 해시는 잘 알고 있지만 MySQL 설명서 에서 다른 것을 찾을 수 있다고 생각합니다. .
"High Performance MySQL"책을 읽는 것이 좋습니다. 위의 답변은 인덱스에 대한 장을 기반으로 한 것입니다.
SELECT last_name, first_name FROM person WHERE last_name= "Constantine"
2.SELECT last_name, first_name FROM person WHERE last_name LIKE "%Constantine"
기본적으로 색인은 순서대로 정렬 된 모든 키의 맵입니다. 순서대로 목록을 작성하면 모든 키를 확인하는 대신 다음과 같은 작업을 수행 할 수 있습니다.
1 : 목록의 중간으로 이동-내가 찾고있는 것보다 높거나 낮습니까?
2 : 높으면 중간과 아래쪽 중간 지점으로 이동하고 낮 으면 중간과 위쪽
3 : 더 높거나 낮습니까? 다시 중간 지점으로 이동
이 논리를 사용하면 모든 항목을 확인하는 대신 약 7 단계로 정렬 된 목록에서 요소를 찾을 수 있습니다.
분명히 복잡성이 있지만 기본 아이디어를 제공합니다.
이 링크를 살펴보십시오 : http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
그들이 작동하는 방식은 하나의 SO 게시물에서 다루기에는 너무 광범위합니다.
다음 은 내가 본 인덱스에 대한 가장 좋은 설명 중 하나입니다. 불행히도 MySQL이 아닌 SQL Server 용입니다. 두 사람이 얼마나 비슷한 지 잘 모르겠습니다 ...
에서 받아 이 인덱싱에 대한 자세한 내용은 동영상
단순 인덱싱 테이블에서 고유 인덱스를 만들 수 있습니다. 고유 색인은 두 행이 동일한 색인 값을 가질 수 없음을 의미합니다. 다음은 테이블에서 인덱스를 작성하는 구문입니다.
CREATE UNIQUE INDEX index_name
ON table_name ( column1, column2,...);
하나 이상의 열을 사용하여 색인을 작성할 수 있습니다. 예를 들어 tutorials_tbl
tutorial_author 를 사용하여 인덱스를 만들 수 있습니다 .
CREATE UNIQUE INDEX AUTHOR_INDEX
ON tutorials_tbl (tutorial_author)
테이블에서 간단한 인덱스를 만들 수 있습니다. 쿼리에서 UNIQUE 키워드를 생략하면 간단한 색인이 생성됩니다. 단순 인덱스는 테이블에서 중복 값을 허용합니다.
열의 값을 내림차순으로 색인화하려는 경우 열 이름 뒤에 예약어 DESC를 추가 할 수 있습니다.
mysql> CREATE UNIQUE INDEX AUTHOR_INDEX
ON tutorials_tbl (tutorial_author DESC)
2 센트를 더하고 싶습니다. 나는 데이터베이스 전문가가 아니었지만 최근이 주제에 대해 조금 읽었습니다. 내가 ELI5를 시도하고 줄 정도로 충분합니다. 그래서 여기 평신도의 설명이 있습니다.
나는 인덱스가 테이블의 미니 미러와 같고 연관 배열과 매우 비슷하다는 것을 이해합니다. 일치하는 키를 제공하면 하나의 "명령"에서 해당 행으로 이동할 수 있습니다.
그러나 해당 인덱스 / 배열이없는 경우 쿼리 인터프리터는 for-loop를 사용하여 모든 행을 통과하고 일치 (전체 테이블 스캔)를 확인해야합니다.
인덱스가 있으면 콘텐츠를 더 빨리 찾는 "업사이드"대신에 추가 스토리지 (그 미니 미러 용)의 "다운 사이드"가 있습니다.
(DB 엔진에 따라) 기본, 외래 또는 고유 키를 생성하면 해당 인덱스도 자동으로 설정됩니다. 같은 원리가 기본적으로 그 키가 작동하는 이유와 방법입니다.
MySQL InnoDB에는 두 가지 유형의 인덱스가 있습니다.
클러스터형 인덱스라고하는 기본 키. 인덱스 키워드는 실제 레코드 데이터와 함께 B + Tree 리프 노드에 저장됩니다.
비 클러스터형 인덱스 인 보조 키. 이 인덱스는 기본 키 키워드와 B + Tree 리프 노드에 자체 인덱스 키워드 만 저장합니다. 따라서 보조 인덱스에서 검색 할 때는 먼저 기본 키 인덱스 키워드를 찾고 기본 키 B + 트리를 스캔하여 실제 데이터 레코드를 찾습니다. 이로 인해 기본 인덱스 검색에 비해 보조 인덱스가 느려집니다. 그러나 select
열이 모두 보조 인덱스에 있으면 기본 인덱스 B + Tree를 다시 찾을 필요가 없습니다. 이것을 커버링 인덱스라고합니다.