느린 인덱싱 및 쿼리 최적화

느린 인덱싱 및 쿼리 최적화

1. 왜 인덱스가

지식 검토 : 데이터는 필연적으로 하드 디스크 IO 작업의 존재에 해당 쿼리 데이터가 필요하다

또한 "키"라는 MySQL의 인덱스에서 신속하게 기록을 찾는 데 사용하는 데이터 구조 스토리지 엔진이다.

  • 기본 키

  • 고유 키

  • 인덱스 키

(기본 키 외래 키 쿼리 속도를 높이기 위해 사용되지 않습니다, 우리는 키의 3 종류 전에 위의 두 가속 쿼리 결과뿐만 아니라 추가적인 제약뿐만 아니라, 연구의 범위 내에 있지 않은 : 비어 있지 만, 고유 키 : 어떤 제약 기능이없는 인덱스 키가 도움이 될 것입니다 동안 만), 당신은 쿼리 속도

인덱스는 디렉토리 북 유사한 데이터 구조입니다. 그것은 나중에 설문 조사 데이터는 데이터 디렉토리를 찾기 위해 먼저가 대신하는 방식의 데이터 페이지를 조회해야 의미

 

2. 지수는 무엇입니까

결국 지속적으로 이벤트의 임의의 순서가 이벤트하게하면서 범위는, 데이터를 얻으려면 축소하여 결과를 필터링 할,

즉,이 인덱싱 메커니즘, 우리는 항상 데이터를 같은 방식을 잠글 볼 수있다.

 

인덱스 3. 충격

  • 인덱스를 생성하는 속도가 느려질 수 있습니다, 테이블에서 많은 양의 데이터의 가용성에 따라

  • 인덱스를 만든 후 테이블에 쿼리 성능이 크게 향상되지만, 쓰기 성능은 감소

 

4. 인덱스 데이터 구조

인덱스, 데이터베이스의 복잡성의 기본 원칙 앞에 말하기뿐만 아니라 운영 체제의 지식에 대해 얘기, 목적은 데이터 구조의 종류, 그 배경과 맥락이있을 것이다 허공 생성되지 않습니다, 모든 사람이 알 수 있도록하는 것입니다 우리 모든 시간은 데이터가 매우 작은 크기에 바람직 일정한 크기를 디스크 IO 컨트롤의 수를 확인하는 방법은 다음과 같습니다 요약, 우리가 무엇을 할 수 있는지,이 데이터 구조를 필요, 그것은 즉, 실제로는 매우 간단합니다. 그런 다음 우리는 고도의 제어 여러 검색 나무 수요를 충족하기 위해 아닌지 궁금해? 이러한 방법으로, B + 트리가 등장 (B + 트리를 통해 이진 검색 트리입니다, 다음, 균형 이진 트리, B 트리 진화).

만 잎 노드는 실제 데이터, 뿌리와 가지 노드가 가상 데이터가 존재 저장

계층 적 의사 결정 트리로 문의의 수, 낮은 수준, 덜 자주

디스크 조각의 크기는 저장 될 수있는 데이터의 특정 량의 특정 방법이다. 어떻게 나무 그것의 최저 수준을 보장하기 위해? 디스크 저장 공간은 데이터 아이템의 상대적으로 작은 편이다

나는 우리가 우리에게 필드는 인덱스 트리의 높이의 수준을 줄일 수있는 내부 테이블을 제공해야한다고 생각 >>> 기본 키 ID 필드

 

클러스터 된 인덱스와 보조 인덱스

1. 클러스터 된 인덱스 (기본 키)

클러스터 인덱스는 실제로 테이블의 기본 키를 참조 테이블에 지정된 이노 엔진은 기본 키가 있어야합니다. 스토리지 엔진에서 첫 모습.

테이블의 구조는 하드 디스크에 해당하는의 MyISAM은 여러 개의 파일 (세)가?

테이블의 구조는 하드 디스크에 해당하는 InnoDB는 여러 개의 파일 (이)가? FRM 파일은 IDB가 테이블 데이터 파일에 데이터 이노 인덱스 수단 인덱스를 넣어 불가능 테이블 구조를 저장한다.

: 특징 넣어 리프 노드의 섹션의 전체 기록을

인덱스의 장점 초점

1 . 정렬 찾기 및 기본 키 검색의 범위가 매우 빠르고, 노드 데이터 사용자가 쿼리 잎입니다. 

기본 키의 데이터가 획득 될 수있는 중간 리프 노드 페이지 범위의 상위 계층에서의 범위를 발견하는 경우 2. 조회 범위 (범위 쿼리), 즉, 다음 페이지를 직접 판독 할 수있다

2. 보조 인덱스 (고유 색인)

보조 인덱스 : 쿼리 데이터 모두도 등 정보 필드 이름, 암호를 사용할 수 있습니다, 선별 ID 조건으로 사용할 수 없습니다, 당신은 쿼리 성능 클러스터 된 인덱스 속도를 높이기 위해이 시간을 사용할 수 없습니다. 그것은 이러한 인덱스가 보조 인덱스라고하며, 다른 필드에 색인을 할 필요가

기능 : 리프 노드 (예를 들어, 상기 보조의 값에 대응하는 레코드 인덱스 필드의 기본 키에 저장된다 : 이름 필드 따른 인덱스 생성은, 그 리프 노드에 저장된다 : 값이 {명칭에 대응 : 기록이있는 것을 마스터의 이름 } 키)

어디 이름 = '제이슨'사용자의 이름을 선택;

위의 문은 커버링 인덱스라고 : 보조 인덱스의 리프 노드는 우리가 원하는 모든 데이터를 발견했다

어디 이름 = '제이슨'사용자의 나이를 선택;

위의 문은 호출되는 비 포함하는 인덱스가 쿼리 필드 이름을 쳤을 때,하지만, 인덱스를하지만 마스터 키를 사용하여 찾을 필요가 있으므로, age 필드하는지 확인

 

 

6. 테스트 색인

1. 준비

#1. 准备表
create table s1(
id int,
name varchar(20),
gender char(6),
email varchar(50)
);

#2. 创建存储过程,实现批量插入记录
delimiter $$ #声明存储过程的结束符号为$$
create procedure auto_insert1()
BEGIN
    declare i int default 1;
    while(i<3000000)do
        insert into s1 values(i,'jason','male',concat('jason',i,'@oldboy'));
        set i=i+1;
    end while;
END$$ #$$结束
delimiter ; #重新声明 分号为结束符号

#3. 查看存储过程
show create procedure auto_insert1\G 

#4. 调用存储过程
call auto_insert1();
View Code

2.在没有任何索引的情况下

# 表没有任何索引的情况下
select * from s1 where id=30000;
# 避免打印带来的时间损耗
select count(id) from s1 where id = 30000;
select count(id) from s1 where id = 1;

# 给id做一个主键
alter table s1 add primary key(id);  # 速度很慢

select count(id) from s1 where id = 1;  # 速度相较于未建索引之前两者差着数量级
select count(id) from s1 where name = 'jason'  # 速度仍然很慢


"""
范围问题
"""
# 并不是加了索引,以后查询的时候按照这个字段速度就一定快   
select count(id) from s1 where id > 1;  # 速度相较于id = 1慢了很多
select count(id) from s1 where id >1 and id < 3;
select count(id) from s1 where id > 1 and id < 10000;
select count(id) from s1 where id != 3;

alter table s1 drop primary key;  # 删除主键 单独再来研究name字段
select count(id) from s1 where name = 'jason';  # 又慢了

create index idx_name on s1(name);  # 给s1表的name字段创建索引
select count(id) from s1 where name = 'jason'  # 仍然很慢!!!
"""
再来看b+树的原理,数据需要区分度比较高,而我们这张表全是jason,根本无法区分
那这个树其实就建成了“一根棍子”
"""
select count(id) from s1 where name = 'xxx';  
# 这个会很快,我就是一根棍,第一个不匹配直接不需要再往下走了
select count(id) from s1 where name like 'xxx';
select count(id) from s1 where name like 'xxx%';
select count(id) from s1 where name like '%xxx';  # 慢 最左匹配特性

# 区分度低的字段不能建索引
drop index idx_name on s1;

# 给id字段建普通的索引
create index idx_id on s1(id);
select count(id) from s1 where id = 3;  # 快了
select count(id) from s1 where id*12 = 3;  # 慢了  索引的字段一定不要参与计算

drop index idx_id on s1;
select count(id) from s1 where name='jason' and gender = 'male' and id = 3 and email = 'xxx';
# 针对上面这种连续多个and的操作,mysql会从左到右先找区分度比较高的索引字段,先将整体范围降下来再去比较其他条件
create index idx_name on s1(name);
select count(id) from s1 where name='jason' and gender = 'male' and id = 3 and email = 'xxx';  # 并没有加速

drop index idx_name on s1;
# 给name,gender这种区分度不高的字段加上索引并不难加快查询速度

create index idx_id on s1(id);
select count(id) from s1 where name='jason' and gender = 'male' and id = 3 and email = 'xxx';  # 快了  先通过id已经讲数据快速锁定成了一条了
select count(id) from s1 where name='jason' and gender = 'male' and id > 3 and email = 'xxx';  # 慢了  基于id查出来的数据仍然很多,然后还要去比较其他字段

drop index idx_id on s1

create index idx_email on s1(email);
select count(id) from s1 where name='jason' and gender = 'male' and id > 3 and email = 'xxx';  # 快 通过email字段一剑封喉 
View Code

联合索引

select count(id) from s1 where name='jason' and gender = 'male' and id > 3 and email = 'xxx';  
# 如果上述四个字段区分度都很高,那给谁建都能加速查询
# 给email加然而不用email字段
select count(id) from s1 where name='jason' and gender = 'male' and id > 3; 
# 给name加然而不用name字段
select count(id) from s1 where gender = 'male' and id > 3; 
# 给gender加然而不用gender字段
select count(id) from s1 where id > 3; 

# 带来的问题是所有的字段都建了索引然而都没有用到,还需要花费四次建立的时间
create index idx_all on s1(email,name,gender,id);  # 最左匹配原则,区分度高的往左放
select count(id) from s1 where name='jason' and gender = 'male' and id > 3 and email = 'xxx';  # 速度变快
View Code

 

추천

출처www.cnblogs.com/xiongying4/p/11401476.html