工做中遇到的99%SQL優化,這裏都能給你解決方案

前幾篇文章介紹了mysql的底層數據結構和mysql優化的神器explain。後臺有些朋友說小強只介紹概念,平時使用仍是一臉懵,強烈要求小強來一篇實戰sql優化,通過週末兩天的整理和總結,sql優化實戰新鮮出爐, 你們平時學習和工做中,遇到的90% 的sql優化都會介紹到,介意篇幅過長,分紅3篇文章哈。mysql

CREATE TABLE `employees` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(24) NOT NULL DEFAULT '' COMMENT '姓名',
  `age` int(20) NOT NULL DEFAULT '0' COMMENT '年齡',
  `position` varchar(20) NOT NULL DEFAULT '' COMMENT '職位',
  `hire_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '入職時間',
  PRIMARY KEY (`id`),
  KEY `idx_name_age_position` (`name`,`age`,`position`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='員工表';

insert into employees(name,age,position,hire_time) values('LiLei', 22, 'manager', NOW())
insert into employees(name,age,position,hire_time) values('HanMeimei', 23, 'dev', NOW())
insert into employees(name,age,position,hire_time) values('Lucy', 23, 'dev', NOW())
複製代碼

全值匹配

索引的字段類型是varchar(n):2字節存儲字符串長度,若是是utf-8, 則長度是3n+2web

EXPLAIN select * from employees where name='LiLei';
複製代碼

explain解析

EXPLAIN select * from employees where name='LiLei' AND age = 22;
複製代碼

explain解析

EXPLAIN select * from employees where name='LiLei' AND age = 22 AND position = 'manager';
複製代碼

explain解析

最左前綴法則

若是索引是多列,要最受最左前綴法則。指的是查詢從索引的最左前列開始而且不跳過索引中的列。如下兩條sql根據最左前綴法則,都不會走索引。sql

EXPLAIN select * from employees where age = 22 AND position='manager';
EXPLAIN select * from employees where position ='manager';
複製代碼

explain解析

索引失效

不要在索引列上作任何操做(計算、函數、類型轉換),會致使索引失效而轉向全表掃描。編程

EXPLAIN select * from employees where name='LiLei';
複製代碼

explain解析

EXPLAIN select * from employees where left(name, 3)='LiLei';
複製代碼

explain解析

給hire_time增長一個普通索引:後端

alter table `employees` ADD INDEX `idx_hire_time`(`hire_time`) USING BTREE;
EXPLAIN select * from employees where date(hire_time) = '2019-08-25';
複製代碼

explain解析

還原最初索引狀態bash

ALTER TABLE `employees` DROP INDEX `idx_hire_time`;
複製代碼

存儲引擎不能使用索引中範圍條件右邊的列

-- EXPLAIN SELECT * FROM employees WHERE name ='LiLei' AND age=22 AND position ='manager';
EXPLAIN SELECT * FROM employees WHERE name ='LiLei' AND age>22 AND position ='manager';
複製代碼

explain解析
看到key_len這個索引長度是78, 也就是隻使用到了前兩個字段name和age,postition沒有使用到索引的。

覆蓋索引

儘可能使用覆蓋索引(只訪問索引的查詢(索引列包含查詢列)),減小selelct * 語句。mysql優化

EXPLAIN SELECT name,age,position FROM employees WHERE name ='LiLei' AND age=22 AND position ='manager';
複製代碼

explain解析

條件判斷

mysql在使用不等於(! = 或者 <>)的時候沒法使用索引會致使全表掃描數據結構

EXPLAIN SELECT * FROM employees WHERE name !='LiLei' ;
複製代碼

explain解析

空值判斷

is null,is not null也沒法使用索引機器學習

EXPLAIN SELECT * FROM employees WHERE name is null;
複製代碼

explain解析

like

like以通配符開頭(‘$abc’)mysql索引失效會變成全表掃描操做編程語言

EXPLAIN SELECT * FROM employees WHERE name LIKE '%Lei';
複製代碼

explain解析

字符串不加單引號索引失效

EXPLAIN SELECT * FROM employees WHERE name ='1000';
EXPLAIN SELECT * FROM employees WHERE name =1000;
複製代碼

explain解析
不加單引號的字符串,mysql底層會使用cust函數將其轉換爲字符串,此時索引失效。

or&in少使用

少用or或in,用它查詢時,mysql不必定使用索引,mysql內部優化器會根據索引比例、表大小等多個因素總體評估是否使用索引。

EXPLAIN SELECT * FROM employees WHERE name ='LiLei' or name='HanMeimei';
複製代碼

explain解析

範圍查詢優化

給年齡添加單值索引

ALTER TABLE `employees`ADD INDEX `idx_age`(`age`) USING BTREE;
EXPLAIN select * from employees where age > 1 and age <= 2000;
複製代碼

explain解析

沒有走索引緣由:mysql內部優化器會根據檢索比例、表大小等多個因素總體評估是否使用索引。 這個例子沒有走索引多是由於單次數據量查詢過大致使優化器最終選擇不走索引。 優化方法:能夠將大的範圍拆分紅多個小範圍。

還沒關注個人公衆號?

  • 掃文末二維碼關注公衆號【小強的進階之路】可領取以下:
  • 學習資料: 1T視頻教程:涵蓋Javaweb先後端教學視頻、機器學習/人工智能教學視頻、Linux系統教程視頻、雅思考試視頻教程;
  • 100多本書:包含C/C++、Java、Python三門編程語言的經典必看圖書、LeetCode題解大全;
  • 軟件工具:幾乎包括你在編程道路上的可能會用到的大部分軟件;
  • 項目源碼:20個JavaWeb項目源碼。
    小強的進階之路二維碼
相關文章
相關標籤/搜索