Mysql 색인 선택 및 최적화 상세 설명
해시 시계
이 진 밸 런 스 트 리:각 노드 의 왼쪽 아들 은 아버지 노드 보다 작고 아버지 노드 는 오른쪽 아들 보다 작 으 며 시간 복잡 도 는 O(log(N)이다.
다 중 균형 트 리:색인 은 메모리 뿐만 아니 라 디스크 에 도 적 혀 있 습 니 다.조회 가 가능 한 한 디스크 를 적 게 읽 도록 하기 위해 서 는 조회 과정 이 가능 한 한 적은 데이터 블록 에 접근 하도록 해 야 한다.따라서'N 포크'트 리 를 사용 해 야 한다.
B+Tree
B-Tree 와 B+Tree
B-Tree
B+Tree
이 노 DB 는 B+트 리 인덱스 모델 을 사용 했다.만약 에 우리 가 메 인 키 가 ID 로 열 거 된 표 가 있다 고 가정 하면 표 에 필드 k 가 있 고 k 에 색인 이 있 습 니 다.다음 과 같 습 니 다.
// 16K、 1K、 6 、 bigint (8 )
//
K = 16*1024/(8+6) =1170
//
N = 16/1 = 16
// B+
V = K*K*N = 21902400
MyISAM 도 B+Tree 색인 을 사용 합 니 다.메 인 키 와 비 메 인 키 색인 을 구분 하지 않 고 모두 비 클 러 스 터 색인 이 며,잎 노드 는 데이터 파일 의 지침 을 저장 합 니 다.색인 선택
최적화 기 가 색인 을 선택 하 는 목적 은 가장 좋 은 실행 방안 을 찾 고 가장 작은 대가 로 문 구 를 실행 하 는 것 이다.데이터베이스 에서 스 캔 줄 수 는 집행 대가 에 영향 을 주 는 요소 중 하나 이다.스 캔 한 줄 수가 적 을 수록 디스크 데이터 에 접근 하 는 횟수 가 적 고 CPU 자원 이 적 다 는 뜻 입 니 다.
물론 스 캔 줄 수 는 유일한 판단 기준 이 아니 며,최적화 기 는 임시 표 사용 여부,정렬 여부 등 을 결합 해 종합 적 으로 판단 한다.
스캐닝 줄 수 는 어떻게 계산 합 니까?
하나의 색인 에 서로 다른 값 이 많 을 수록 이 색인 의 구분 도 는 더욱 좋다.색인 에 있 는 서로 다른 값 의 개 수 를'기수'(cardinality)라 고 합 니 다.
--
mysql> show index from test;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| test | 0 | PRIMARY | 1 | id | A | 100256 | NULL | NULL | | BTREE | | |
| test | 1 | index_a | 1 | a | A | 98199 | NULL | NULL | YES | BTREE | | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
성능 측면 에서 볼 때 InnoDB 는 샘플링 통 계 를 사용 하여 기본적으로 N 개의 데이터 페이지 를 선택 하고 이 페이지 의 서로 다른 값 을 통계 하여 평균 값 을 얻 은 다음 에 이 색인 의 페이지 수 를 곱 하면 이 색인 의 기 수 를 얻 을 수 있다.따라서 상기 두 색인 에 표 시 된 기 수 는 같 지 않다.데이터 시트 는 지속 적 으로 업데이트 되 고 색인 통계 정보 도 고정 되 지 않 습 니 다.따라서 변 경 된 데이터 줄 수가 1/M 을 넘 을 때(innodbstats_persistent=on 시 기본 10,반대로 16)색인 통 계 를 다시 만 드 는 것 이 자동 으로 실 행 됩 니 다.
mysql> show variables like '%innodb_stats_persistent%';
+--------------------------------------+-------------+
| Variable_name | Value |
+--------------------------------------+-------------+
-- , 10%
| innodb_stats_auto_recalc | ON |
--
| innodb_stats_include_delete_marked | OFF |
-- null , nulls_equal , NULL
| innodb_stats_method | nulls_equal |
--
| innodb_stats_on_metadata | OFF |
--
| innodb_stats_persistent | ON |
-- innodb_stats_persistent=on,
| innodb_stats_persistent_sample_pages | 20 |
-- , innodb_stats_transient_sample_pages
| innodb_stats_sample_pages | 8 |
-- page
| innodb_stats_transient_sample_pages | 8 |
+--------------------------------------+-------------+
--
mysql> analyze table t;
정렬 이 색인 선택 에 미 치 는 영향
--
mysql> CREATE TABLE `t` (
`id` int(11) NOT NULL,
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`),
KEY `b` (`b`)
) ENGINE=InnoDB;
--
mysql> delimiter ;
CREATE PROCEDURE idata ()
BEGIN
DECLARE i INT ;
SET i = 1 ;
WHILE (i <= 100000) DO
INSERT INTO t
VALUES
(i, i, i) ;
SET i = i + 1 ;
END
WHILE ;
END;
delimiter ;
-- ,
mysql> CALL idata ();
-- , a
mysql> explain select * from t where a between 10000 and 20000;
+----+-------------+-------+-------+---------------+-----+---------+------+-------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+-----+---------+------+-------+-----------------------+
| 1 | SIMPLE | t | range | a | a | 5 | NULL | 10000 | Using index condition |
+----+-------------+-------+-------+---------------+-----+---------+------+-------+-----------------------+
-- b , b , , , b,
mysql> explain select * from t where (a between 1 and 1000) and (b between 50000 and 100000) order by b limit 1;
+----+-------------+-------+-------+---------------+-----+---------+------+-------+------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+-----+---------+------+-------+------------------------------------+
| 1 | SIMPLE | t | range | a,b | b | 5 | NULL | 50128 | Using index condition; Using where |
+----+-------------+-------+-------+---------------+-----+---------+------+-------+------------------------------------+
-- 1: force index a, , ( , )
mysql> explain select * from t force index(a) where (a between 1 and 1000) and (b between 50000 and 100000) order by b limit 1;
+----+-------------+-------+-------+---------------+-----+---------+------+------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+-----+---------+------+------+----------------------------------------------------+
| 1 | SIMPLE | t | range | a | a | 5 | NULL | 999 | Using index condition; Using where; Using filesort |
+----+-------------+-------+-------+---------------+-----+---------+------+------+----------------------------------------------------+
-- 2: MySQL , b,a , a
mysql> explain select * from t where (a between 1 and 1000) and (b between 50000 and 100000) order by b,a limit 1;
+----+-------------+-------+-------+---------------+-----+---------+------+------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+-----+---------+------+------+----------------------------------------------------+
| 1 | SIMPLE | t | range | a,b | a | 5 | NULL | 999 | Using index condition; Using where; Using filesort |
+----+-------------+-------+-------+---------------+-----+---------+------+------+----------------------------------------------------+
-- 3: , , ,
ALTER TABLE `t`
DROP INDEX `a`,
DROP INDEX `b`,
ADD INDEX `ab` (`a`,`b`) ;
색인 최적화색인 선택성
색인 선택성
-- t xxx
select count(distinct xxx)/count(id) from t;
색인 의 선택성 은 중복 되 지 않 는 색인 값(기수)과 표 기록 수의 비례 를 가리킨다.선택성 은 색인 선별 능력 의 한 지표 로 색인 의 수치 범 위 는 0~1 이 며 선택성 이 클 수록 색인 가치 도 커진다.일반 색인 조 회 를 사용 할 때 일반 색인 을 불 러 오고 일반 색인 을 통 해 실제 줄 의 홈 키 를 조회 한 다음 에 홈 키 를 사용 하여 색인 을 모 아 해당 줄 을 조회 하여 모든 줄 을 순환 적 으로 조회 합 니 다.전체 색인 을 직접 검색 하면 일반 색인 과 집합 색인 을 오 가 며 전환 할 필요 가 없 으 며,두 가지 작업 의 총 비용 보다 전체 표를 스 캔 하 는 효율 이 높 을 수 있 습 니 다.
실제 업무 에 서 는 업무 상황 을 봐 야 한다.만약 에 데이터 분포 가 불 균형 하면 실제 조회 조건 은 데이터 가 비교적 적은 부분 을 조회 하고 색인 선택 이 비교적 낮은 열 에 색인 을 추가 하면 효과 도 좋 을 것 이다.
겹 쳐 쓰기 인덱스
덮어 쓰기 인덱스 는 트 리 의 검색 횟수 를 줄 이 고 검색 성능 을 현저히 향상 시 킬 수 있 기 때문에 덮어 쓰기 인덱스 를 사용 하 는 것 은 자주 사용 하 는 성능 최적화 수단 이다
-- ID , ID k , ,
select ID from T where k between 3 and 5
-- V, V, k、v
select ID,V from T where k between 3 and 5
맨 왼쪽 접두사 원칙+색인 아래 밀어 내기
-- id、name、age ,name、age
-- ,name、age
select * from T where name='xxx' and age=12
-- Mysql , name、age ,,name、age
select * from T where age=12 and name='xxx'
-- name ,MySQL5.6 (index condition pushdown), age=12
select * from T where name like 'xxx%' and age=12
-- ,
select * from T where name like '%xxx%' and age=12
-- ,name
select * from T where name='xxx'
-- ,
select * from T where age=12
연합 색인 생 성 원칙:
mysql> create table SUser(
ID bigint unsigned primary key,
name varchar(64),
email varchar(64),
...
)engine=innodb;
--
mysql> select name from SUser where email='xxx';
-- 1: ,
mysql> alter table SUser add index index1(email);
-- 2: ,
mysql> alter table SUser add index index2(email(6));
접두사 색인 은 공간 을 절약 할 수 있 지만 접두사 길이 의 정 의 를 주의해 야 합 니 다.공간 을 절약 하 는 동시에 조회 원 가 를 너무 많이 증가 해 서 는 안 됩 니 다.즉,리 턴 검증 횟수 를 줄 이 는 것 입 니 다.어떻게 적합 한 접두사 길 이 를 설정 합 니까?
-- ,
select count(distinct left(email,n))/count(distinct email) from SUser;
적당 한 접두사 길이 가 길 면?예 를 들 어 신분증 번호 가 구역 구분 요 구 를 만족 시 키 면 12 비트 이상 의 접두사 색인 이 필요 할 수 있 고 절약 하 는 공간 이 유한 하 며 조회 원 가 를 증가 하면 접두사 색인 을 사용 할 필요 가 없다.이때 우 리 는 다음 과 같은 방식 을 고려 할 수 있다.
역순 저장 소
--
mysql> select field_list from t where id_card = reverse('input_id_card_string');
hash 필드 사용 하기
-- , ,
mysql> alter table t add id_card_crc int unsigned, add index(id_card_crc);
-- hash ,
mysql> select field_list from t where id_card_crc=crc32('input_id_card_string') and id_card='input_id_card_string'
상기 두 가지 방식 의 단점:
--
select id,email from SUser where email='xxx';
유일한 인덱스일반 색인 을 사용 하 는 것 을 권장 합 니 다.유일한 색인 은 change buffer 를 사용 할 수 없고 메모리 명중률 이 낮 습 니 다.
인덱스 실효
총결산
Mysql 색인 선택 및 최적화 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 Mysql 색인 선택 최적화 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
MySQL에서 JSON 인덱싱 - aarondfrancis사람들은 종종 MySQL로 JSON을 인덱싱할 수 없다고 말하지만 완전히 정확하지는 않습니다. MySQL로 JSON 열을 인덱싱하는 것은 완전히 가능합니다! 사람들은 종종 MySQL로 JSON을 인덱싱할 수 없다고 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.