MySQL 성능 [인덱스 최적화 분석]

SQL 성능 저하

SQL 성능 저하의 몇 가지 이유 :

  • 잘못된 SQL
  • 색인이 사용되었지만 색인이 유효하지 않습니다.
  • 관련 쿼리에 너무 많은 조인 (디자인 결함 또는 피할 수없는 요구 사항)
  • 서버 조정 및 다양한 매개 변수 설정 (예 : 버퍼, 스레드 크기 설정 등)

쿼리 결합

MySQL SQL 문 실행 순서
여기에 사진 설명 삽입

요약하자면
여기에 사진 설명 삽입

7 가지 조인 쿼리

// 内连接两表共有内容
select * from emp a inner join dept b on a.deptId=b.id
// 左连接左表全有 && 两表共有内容
select * from emp a left join dept b on a.deptId=b.id
// 右连接右表全有 && 两表共有内容
select * from emp a right join dept b on a.deptId=b.id
// 左连接 左表独有内容
select * from emp a left join dept b on a.deptId=b.id where b.id is null
// 右连接 右表独有内容
select * from emp a right join dept b on a.deptId=b.id where a.deptId is null
// 全连接 两表全部内容【union 去除重复数据】
select * from emp a left join dept b on a.deptId=b.id
union
select * from emp a right join dept b on a.deptId=b.id
// 全连接 两表独有内容
select * from emp a left join dept b on a.deptId=b.id where b.id is null
union
select * from emp a right join dept b on a.deptId=b.id where a.deptId is null

색인 소개

공식 정의 : 인덱스 인덱스는 MySQL이 데이터를 효율적으로 가져 오는 데 도움이되는 데이터 구조입니다. 따라서 결론을 도출 할 수 있습니다.**索引的本质就是数据结构。**

인덱스 란 무엇입니까?

排好序的快速查找数据结构

데이터 자체 외에도 데이터베이스는 특정 검색 알고리즘을 만족하는 데이터 구조를 유지합니다. 이러한 데이터 구조는 특정 방식으로 데이터를 가리 키므로 이러한 데이터 구조를 기반으로 고급 검색 알고리즘을 구현할 수 있습니다.이 데이터 구조는 인덱스입니다.

일반적으로 색인 자체도 매우 크고 모든 것을 메모리에 저장하는 것이 불가능하므로 색인 파일 형태로 디스크에 저장되는 경우가 많습니다.

우리가 일반적으로 참조하는 인덱스는 달리 지정하지 않는 한 B- 트리 (반드시 이진이 아닌 다중 검색 트리) 구조로 구성된 인덱스를 참조합니다. 그중 클러스터형 인덱스, 보조 인덱스, 커버링 인덱스, 복합 인덱스, 접두사 인덱스, 고유 인덱스는 모두 기본적으로 인덱스라고하는 B + 트리 인덱스를 사용합니다. B + 트리 유형 인덱스 외에도 해시 인덱스 (해시, 인덱스) 등이 있습니다.

인덱싱의 장점

대학 도서관에 서지 색인을 설정하는 것과 유사하게 데이터 검색의 효율성을 높이고 데이터베이스의 IO 비용을 줄입니다.
색인 열을 통해 데이터를 정렬하면 데이터 정렬 비용이 절감되고 CPU 사용량이 감소합니다.

인덱스 단점

실제로 인덱스는 기본 키와 인덱스 필드를 저장하고 엔터티 테이블의 레코드를 가리키는 테이블이기도하므로 인덱스 열도 공간을 차지합니다.

인덱스는 쿼리 속도를 크게 향상 시키지만 테이블 삽입, 업데이트 및 삭제와 같은 테이블 업데이트 속도도 줄입니다. 테이블을 업데이트 할 때 MySQL은 데이터를 저장할뿐만 아니라 인덱스 열 필드를 추가하기 위해 인덱스 파일이 업데이트 될 때마다 인덱스 파일도 저장하기 때문에 업데이트로 인한 키 값 변경 후 인덱스 정보를 조정합니다.

인덱스는 효율성을 향상시키는 요소 일뿐입니다. MySQL에 많은 양의 데이터가 포함 된 테이블이있는 경우 최상의 인덱스를 조사하고 설정하거나 쿼리를 최적화하는 데 시간을 투자해야합니다.

mysql 인덱스 분류

  • 단일 인덱스

即一个索引只包含单个列,一个表可以有多个单列索引。

  • 고유 색인

索引的值必须是唯一的,但允许有空值。

  • 복합 지수

即一个索引包含多个列

  • 기본 문법
// 单独创建索引
create [unique] index indexName ON mytable(columnName(length));
// 创建表的同时创建索引
alter mytable add [unique] index [indexName] ON (columnName(lenght));
// 删除索引
drop index [indexName] ON mytable;
// 查看索引
show index from table_name;

데이터 테이블의 인덱스를 추가하는 네 가지 방법 :

// 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为 NULL
ALTER table table_name ADD PRIMARY KEY(column_list);
// 该语句创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)。
ALTER table table_name ADD UNIQUE index_name(column_list);
// 添加普通索引,索引值可出现多次。
ALTER table table_name ADD INDEX index_name(column_list);
// 该语句指定了索引为 FULLTEXT,用于全文索引
ALTER table table_name ADD FULLTEXT index_name(column_list);

mysql 인덱스 구조

BTree 索引

Hash 索引

full-text 全文索引

R-Tree 索引

인덱스 생성에 필요한 상황

  1. 기본 키는 자동으로 고유 인덱스를 생성합니다.
  2. 쿼리 조건으로 자주 사용되는 필드는 인덱싱되어야합니다.
  3. 쿼리의 다른 테이블과 연결된 필드를 쿼리하고 외래 키 관계에 대한 인덱스를 만듭니다.
  4. 단일 키 / 결합 된 인덱스 선택 문제 (높은 동시성이 복합 인덱스를 생성하는 경향이 있음)
  5. 쿼리의 정렬 필드는 인덱스를 통해 정렬 필드에 액세스하면 정렬 속도가 크게 향상됩니다.
  6. 쿼리의 통계 또는 그룹화 필드.

색인을 만들지 않는 경우

  1. 자주 업데이트되는 필드는 인덱스 생성에 적합하지 않습니다.
  2. Where 조건에서 사용되지 않는 필드는 인덱싱되지 않습니다.
  3. 테이블 필드가 너무 적습니다.
  4. 반복되고 균등하게 분산 된 데이터가있는 테이블 필드이므로 가장 자주 쿼리되고 가장 자주 정렬되는 데이터에 대한 인덱스 만 작성해야합니다. 데이터 열에 중복 콘텐츠가 많이 포함되어있는 경우이를 인덱싱하면 실질적인 효과가별로 없습니다.

성능 분석

MySql 쿼리 최적화 프로그램

  1. MySQL에는 특히 SELECT 문 최적화를 담당하는 Optimizer 모듈이 있습니다. 주요 기능은 계산 및 분석 시스템에서 수집 된 통계 정보를 제공하여 클라이언트가 요청한 쿼리에 자신이 생각하는 최상의 실행 계획을 제공하는 것입니다.이 부분은 가장 시간이 많이 소요되는 부분입니다.
  2. 클라이언트가 MySQL에서 쿼리를 요청하면 명령 파서 모듈이 요청 분류를 완료합니다. 차이가 SELECT이고 MySQL Query Optimizer로 전달되면 MySQL Query Optimizer는 먼저 전체 쿼리를 최적화하여 일부 상수 표현식의 예산을 처리합니다. 상수 값으로 직접 변환합니다. 쓸모 없거나 명백한 일부 조건 제거, 구조적 조정 등과 같이 Query에서 쿼리 조건을 단순화하고 변환합니다. 그런 다음 쿼리의 힌트 정보 (있는 경우)를 분석하여 힌트 정보를 표시하여 쿼리의 실행 계획을 완전히 결정할 수 있는지 확인합니다. Hint가 없거나 Hint 정보가 부족하여 실행 계획을 완벽하게 결정할 수없는 경우 관련 객체의 통계 정보를 읽고 Query에 따라 해당 계산 및 분석을 작성하여 최종 실행 계획을 얻습니다.

MySQL의 일반적인 병목 현상

  1. CPU :CPU在饱和的时候一般发生在数据装入内存或从磁盘上读取数据的时候。
  2. 나는:磁盘 I/O 瓶颈发生在装入数据远大于内存容量的时候。
  3. 서버 하드웨어의 성능 병목 현상 :top,free,iostat和vmstat来查看系统的性能状态

설명

Explain 又称为 【查看执行计划】

Explain 키워드를 사용하여 최적화 프로그램이 실행하는 SQL 쿼리를 시뮬레이션하여 MySQL이 SQL 문을 처리하는 방법을 알 수 있습니다. 쿼리 또는 테이블 구조의 성능 병목 현상을 분석합니다.

Explain 사용 방법

explain + SQL 语句

여기에 사진 설명 삽입
포함 된 정보 :

신분증 select_type 유형 possible_keys key_len 심판 특별한

Explain의 역할

  1. 查看表的读取顺序
  2. 查看数据读取操作的操作类型
  3. 查看哪些索引可以使用
  4. 查看哪些索引被实际使用
  5. 查看表之间的引用关系
  6. 查看每张表有多少行被优化器查询

설명의 ID 필드 기능

쿼리에서 select 절 또는 작업 테이블이 실행되는 순서를 나타내는 숫자 집합을 포함한 선택 쿼리의 시퀀스 번호

id 필드에는 세 가지 상황이 있습니다.

  1. ID는 동일하고 실행 순서는 위에서 아래로
  2. 아이디가 다릅니다. 서브 쿼리 인 경우 아이디의 일련 번호가 증가합니다. 아이디 값이 클수록 우선 순위가 높고 더 빨리 실행됩니다.
  3. 같은 아이디이지만 다른

id가 같으면 그룹으로 간주하여 위에서 아래
순서대로 실행 가능; 모든 그룹에서 id 값이 클수록 우선 순위가 높을수록 더 빨리 실행 됨;
파생 상품 = DERIVED

Explain의 select_type 및 테이블 필드 함수

select_type의 일반적인 값 :

신분증 select_type
1 단순한
2 일 순위
서브 쿼리
4 파생
5 노동 조합
6 연합 결과

쿼리 유형은 주로 구별을 위해 사용됩니다.
일반 쿼리, 공동 쿼리 및 하위 쿼리와 같은 복잡한 쿼리.

  1. 단순 : 단순 선택 쿼리, 쿼리에 하위 쿼리 또는 공용체가 포함되지 않음
  2. PRIMARY : 쿼리에 복잡한 하위 부분이 포함 된 경우 가장 바깥 쪽 쿼리가 기본 쿼리로 표시됩니다.
  3. SUBQUERY : 하위 쿼리가 select 또는 where 목록에 포함됩니다.
  4. DERIVED : from 목록에 포함 된 하위 쿼리는 DERIVED 파생 된 것으로 표시됩니다. MySQL은 이러한 하위 쿼리를 반복적으로 실행하고 결과를 임시 테이블에 배치합니다.
  5. UNION : 두 번째 선택이 공용체 뒤에 나타나면 공용체로 표시됩니다. 공용체가 from 절의 하위 쿼리에 포함 된 경우 외부 선택은 다음과 같이 표시됩니다. DERIVED
  6. UNION RESULT : 통합 테이블 선택에서 결과 가져 오기

테이블 :이 행의 데이터가 어떤 테이블에 관한 것인지 보여줍니다.

Explain의 유형 필드 함수

type은 액세스 유형의 배열을 나타내고 type은 액세스 유형을 나타내며 더 중요한 지표 인 결과值从最好到最坏依次是:

system>const>eq_ref>ref>fulltext>ref_or_null>index_merge>unique_subquery>index_subquery>range>index>ALL

시스템> conft> eq_ref> ref> range> index> ALL

일반적으로 쿼리가 적어도 범위 수준 (가급적이면 ref)에 도달하는지 확인해야합니다.

유형에 대한 일반적인 값 :

모두 인덱스 범위 심판 eq_ref const, 시스템 없는

어떤 유형의 쿼리가 사용되는지 보여줍니다.从最好到最差依次是:
system>const>en_ref>ref>range>index>ALL

  1. 시스템 : 테이블에 하나의 레코드 행만 있습니다 (시스템 테이블과 동일). 이것은 const 유형의 특수 열이며 일반적으로 나타나지 않으며 무시할 수도 있습니다.
  2. const : 인덱스별로 한 번만 찾을 수 있음을 의미하며, const는 기본 키 또는 고유 인덱스를 비교하는 데 사용됩니다. 한 행의 데이터 만 일치하기 때문에 매우 빠르며 기본 키가 where 목록에 있으면 MySQL은 쿼리를 상수로 변환 할 수 있습니다.
  3. ep_ref : 고유 인덱스 스캔 각 인덱스 키에 대해 테이블에 일치하는 레코드가 하나만 있습니다. 일반적으로 기본 키 또는 고유 인덱스 스캔에 사용됩니다.
  4. ref : 단일 값과 일치하는 모든 행을 반환하는 고유하지 않은 색인 스캔은 기본적으로 색인 액세스입니다. 단일 값과 일치하는 모든 행을 반환하지만 여러 적합한 행을 찾을 수 있습니다. 따라서 그는 검색과 스캔의 하이브리드 여야합니다.
  5. 범위 : 지정된 범위의 행만 확인하고 인덱스를 사용하여 행을 선택합니다. 키 열에는 사용되는 인덱스가 표시됩니다. 일반적으로 between, <,> in과 같은 쿼리가 where 문에 나타납니다.이 범위 스캔 인덱스는 인덱스의 특정 지점에서만 시작하면되므로 전체 테이블 스캔보다 빠릅니다. , 그리고 모든 인덱스를 스캔하지 않고 다른 지점에서 끝납니다.
  6. index : 전체 인덱스 스캔, 인덱스와 ALL의 차이점은 인덱스 유형이 인덱스 트리 만 통과한다는 것입니다. 인덱스 파일은 일반적으로 데이터 파일보다 작기 때문에 일반적으로 ALL보다 빠릅니다. (즉, all과 Index는 모두 전체 테이블을 읽지 만 인덱스는 인덱스에서 읽고 모두는 하드 디스크에서 읽습니다.)
  7. all : 전체 테이블 스캔, 일치하는 행을 찾기 위해 전체 테이블을 탐색합니다.

possible_keys 및 키 필드 기능 설명

  • possible_keys

이 테이블에 적용될 수있는 하나 이상의 인덱스를 표시합니다.
색인이있는 경우 필드와 관련된 쿼리는 색인이 나열됩니다 但不一定要被查询实际使用.

실제로 사용되는 인덱스, NULL이면 사용하지 않는 인덱스
查询中若使用了覆盖索引,则该索引仅出现在 key 列表中

설명의 key_len 필드 함수

인덱스에 사용 된 바이트 수를 나타냅니다.이 열은 질의에 사용 된 인덱스 길이를 계산하는 데 사용할 수 있습니다. 정확도를 잃지 않고 길이가 짧을수록 좋습니다.
key_len에 의해 표시되는 값은 인덱스 필드의 가능한 최대 길이입니다. 并非实际使用长度즉, key_len은 테이블에서 검색되지 않고 테이블 정의에 따라 계산됩니다.

Explain의 참조 필드 함수

가능한 경우 상수로 사용되는 인덱스의 열을 표시합니다. 인덱싱 된 열에서 값을 찾는 데 사용되는 열 또는 상수입니다.

쿼리의 다른 테이블과 연결된 필드를 쿼리하고 외래 키 관계에 대한 인덱스를 만듭니다.

Explain의 행 필드 함수

테이블 통계 및 인덱스 선택에 따라 필요한 레코드를 찾기 위해 읽어야하는 행 수를 대략적으로 추정합니다.

Explain의 추가 필드 기능

추가 중요 정보 기록

일반적인 값은 다음과 같습니다.

  1. Using filesort: Mysql은 테이블의 인덱스 순서에 따라 데이터를 읽는 대신 외부 인덱스를 사용하여 데이터를 정렬합니다. MySQL에서 인덱스를 사용하여 수행 할 수없는 정렬 작업을 "파일 정렬"이라고합니다.
  2. Using temporary: 임시 테이블은 중간 결과를 저장하는 데 사용되며 MySQL은 쿼리 결과를 정렬 할 때 임시 테이블을 사용합니다. 일반적으로 정렬 기준 및 그룹 질의 그룹 기준에 사용됩니다.
  3. Using index: 테이블의 데이터 행에 대한 액세스를 피하기 위해 해당 선택 작업에서 커버링 인덱스 (Covering Index)가 사용됨을 나타내며 효율성이 좋습니다! where가 동시에 나타나는 경우 인덱스가 인덱스 키 값을 검색하는 데 사용됨을 나타내고 where가 동시에 나타나지 않는 경우 인덱스가 검색을 수행하는 대신 데이터를 읽는 데 사용됨을 나타냅니다.覆盖索引(Covering Index)

커버링 인덱스 : 선택의 데이터 열은 데이터 행을 읽지 않고 인덱스에서만 가져올 수 있으며, MySQL은 인덱스에 따라 데이터 파일을 다시 읽을 필요없이 인덱스를 사용하여 선택 목록의 필드를 반환 할 수 있습니다.查询列要被所创建的索引覆盖。

참고 : 커버링 인덱스를 사용하려면 *를 선택하지 말고 선택 목록에서 필요한 열만 제거해야합니다. 모든 필드가 함께 인덱싱되면 인덱스 파일이 너무 커지고 쿼리 성능이 저하되기 때문입니다.

  1. Using where: SQL이 필터링 위치를 사용함을 나타냅니다.
  2. using join buffer:이 SQL 조각이 연결 캐시를 사용함을 나타냅니다.
  3. impossible where: SQL 문의 where 절의 값이 항상 false이고 튜플을 얻는 데 사용할 수 없음을 나타냅니다.
  4. select tables optimized away: group by없이 인덱스를 기반으로 최소 / 최대 연산을 최적화하거나 MyISAM 스토리지 엔진의 count (*) 연산을 최적화합니다. 계산을 수행하기 위해 실행 단계까지 기다릴 필요가 없습니다. 질의 실행 계획 생성 단계가 최적화됩니다.
  5. distinct: 고유 한 작업을 최적화하고 일치하는 첫 번째 튜플을 찾은 후 동일한 가치있는 작업을 찾는 것을 중지합니다.

인덱스 최적화

지수 분석

  • 단일 테이블 분석 : 일반적으로 필드를 쿼리하여 인덱스 최적화를 잘 구축하는 데 사용됩니다.
  • Two-table 분석 : 왼쪽 조인 인덱스는 오른쪽 테이블에, 오른쪽 테이블은 왼쪽 테이블에 구축하는 것이 좋지만, 반대로 서로 인덱스를 생성하여 최적화 할 수 있습니다.
  • 3- 테이블 분석 : 두 테이블과 동일하지만 인덱스 최적화를 생성하기 위해 다른 두 테이블과 반대입니다.

인덱스 실패

  1. 전체 경기
  2. 가장 왼쪽 접두사 규칙

인덱스에 여러 열이 포함 된 경우 맨 왼쪽 접두사 규칙을 따르십시오. 즉, 쿼리가 인덱스의 맨 왼쪽 앞 열에서 시작되고 인덱스의 열을 건너 뛰지 않습니다.

  1. 인덱스 열에서 어떤 작업 (계산, 함수, 자동 또는 수동 유형 변환)을 수행하지 마십시오. 그러면 인덱스가 실패하고 전체 테이블 스캔으로 전환됩니다.
  2. 스토리지 엔진은 인덱스의 범위 조건 오른쪽에있는 열을 사용할 수 없습니다.
  3. 커버링 인덱스 (인덱스 쿼리 (인덱스 열 및 쿼리 열)에만 액세스)를 사용하고 select *를 줄이십시오.
  4. MySQL은 인덱스가 (! = 또는 <>)와 같지 않으면 사용할 수 없으므로 전체 테이블 스캔이 발생합니다.
  5. null, null이 아님 또한 인덱스를 사용할 수 없음
  6. 유사한 와일드 카드는 % ( '% abc ...')로 시작됩니다. mysql 인덱스 실패는 전체 테이블 스캔 작업이됩니다.
  7. 작은 따옴표가없는 문자열의 색인이 유효하지 않습니다.
  8. 사용하거나 드물게는 색인을 사용하여 연결할 때 실패합니다.

인터뷰 질문 : '% abc %'와 (과) 같은 경우 인덱스가 유효하지 않은 방법을 어떻게 해결합니까?
같은 쿼리 중에 인덱스가 실패하지 않도록하기위한 전제 조건은 %가 문자열의 오른쪽에 추가되어 인덱스가 무효화되지 않도록 'abc %'와 같은 것임을 모두 알고 있지만 현재 조건은 '%와 같은 전체 퍼지 쿼리를 만들어야한다는 것입니다. abc % ', 이런 식으로 인덱스를 작성하면 100 % 실패합니다.이 문제를 해결하는 방법은 무엇입니까?

: 우리는 예를 들어, 최적화에 포함하는 인덱스를 추가 할 수 있습니다, 쿼리 조건은, 우리가 같은 필드에 인덱스를 추가 이름
, 이름 '이 % ABC %'같은 곳 테이블에서 선택 *
(가) 분석을 설명 후, 위의 SQL을 사용하지 않는 Index, 우리는
'% abc %'와 같은 이름이있는 테이블 에서이 sql select name을 변경할 수 있습니다 .
위의 SQL을 다시 분석 한 후 마침내 인덱스가 실제로 사용됨을 발견합니다. 그러면 like full fuzzy query를 사용해도 해결 될 수 있습니다. 색인 실패의 문제.
**这里要注意的事情:覆盖索引优化的前提是 select 查询的字段正好和你的索引字段数量一致的前提下,简单来说:覆盖索引字段和你select 的字段一致或小于其字段。**

일반적인 조언

  1. 단일 키 인덱스의 경우 현재 쿼리에 대해 더 나은 필터링 성능을 가진 인덱스를 선택하십시오.
  2. 복합 인덱스를 선택할 때 현재 쿼리에서 필터링 가능성이 가장 좋은 필드는 인덱스 필드 시퀀스에 있으며 위치가 높을수록 좋습니다.
  3. 복합 색인을 선택할 때 현재 쿼리의 where 절에 더 많은 필드를 포함 할 수있는 색인을 선택하십시오.
  4. 통계 정보를 분석하고 적절한 색인을 선택하는 목적을 달성하기 위해 쿼리의 문구를 조정하십시오.

추천

출처blog.csdn.net/qq_43647359/article/details/105822524