1. 程式人生 > 其它 >【資料庫】之MySQL索引優化

【資料庫】之MySQL索引優化

技術標籤:MySQL學習筆記mysql資料庫索引sql

DROP TABLE IF EXISTS `staffs`;
CREATE TABLE `staffs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(24) NOT NULL,
  `age` int(11) NOT NULL DEFAULT '0',
  `pos` varchar(20) NOT NULL,
  `add_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into staffs(name,age,pos,add_time) values ('z3',22,'manager',NOW()); insert into staffs(name,age,pos,add_time) values ('july',23,'dex',NOW()); insert into staffs(name,age,pos,add_time) values ('2000',23,'manager',NOW()); alter table
staffs add index idx_staffs_nap(name,age,pos);

1.全值匹配我最愛

EXPLAIN SELECT * FROM staffs WHERE NAME = 'July';

在這裡插入圖片描述

EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' AND age = 25;

在這裡插入圖片描述

EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' AND age = 25 AND pos = 'dev';

在這裡插入圖片描述

2.最佳左字首法則

如果索引了多例,要遵守最左字首法則。指的是查詢從索引的最左前列開始並且不跳過索引中的列。

EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' AND age = 23 AND pos = 'dev';

在這裡插入圖片描述

最左前列索引不能丟

EXPLAIN SELECT * FROM staffs WHERE age = 23 AND pos = 'dev';

在這裡插入圖片描述

不能跳過中間列索引

只用到了第一個索引

EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' AND pos = 'dev';

在這裡插入圖片描述

EXPLAIN SELECT * FROM staffs WHERE NAME = 'July';

在這裡插入圖片描述

3.不在索引列上做任何操作

計算、函式、(自動or手動)型別轉換等,會導致索引失效而轉向全表掃描

EXPLAIN SELECT * FROM staffs WHERE NAME = 'July';

在這裡插入圖片描述

EXPLAIN SELECT * FROM staffs WHERE left(NAME,4) = 'July';

在這裡插入圖片描述

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

範圍之後全失效

EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' AND age = 25 AND pos = 'manager';

在這裡插入圖片描述

EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' AND age > 25 AND pos = 'manager';

在這裡插入圖片描述

5.儘量使用覆蓋索引

只訪問索引的查詢即索引列和查詢列一致或在索引列內,減少select *

EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' AND age = 25 AND pos = 'manager';

在這裡插入圖片描述

EXPLAIN SELECT name,age,pos FROM staffs WHERE NAME = 'July' AND age = 25 AND pos = 'manager';

在這裡插入圖片描述

6.MySQL在使用不等於(!=或者<>)的時候無法使用索引會導致全表掃描

explain select * from staffs where name = 'July';

在這裡插入圖片描述

explain select * from staffs where name != 'July';

在這裡插入圖片描述

explain select * from staffs where name <> 'July';

在這裡插入圖片描述

7.is null,is not null 也無法使用索引

explain select * from staffs where name is null;

在這裡插入圖片描述

explain select * from staffs where name is not null;

在這裡插入圖片描述

8.like以萬用字元開頭(’$abc…’)MySQL 索引失效會變成全表掃描操作。

like百分號寫右邊

explain select * from staffs where name like '%July';

在這裡插入圖片描述

explain select * from staffs where name like '%July%';

在這裡插入圖片描述

explain select * from staffs where name like 'July%';

在這裡插入圖片描述

問題:解決like’%字串%'時索引不被使用的方法

實驗證明,覆蓋索引,可以解決左右百分號全表掃描的問題。

CREATE TABLE `tbl_user`(
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(30) DEFAULT NULL,
  `age` INT(11) DEFAULT NULL,
  `email` VARCHAR(20)  DEFAULT NULL,
  PRIMARY KEY (`id`)
)ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
 
insert into tbl_user(name,age,email) values ('1aa1',21,'[email protected]');
insert into tbl_user(name,age,email) values ('2aa2',222,'[email protected]');
insert into tbl_user(name,age,email) values ('3aa3',265,'[email protected]');
insert into tbl_user(name,age,email) values ('4aa4',21,'[email protected]');
select * from tbl_user;

在這裡插入圖片描述

select * from tbl_user where name like '%aa%';

在這裡插入圖片描述

select * from tbl_user where name like 'aa%';
# Empty set
select * from tbl_user where name like '%aa';
# Empty set

建索引前,全表掃描,建立索引後用覆蓋索引

索引建立前後對比

create index idx_user_name_age on tbl_user(name,age);
explain select name,age from tbl_user where name like '%aa%'; 

在這裡插入圖片描述
在這裡插入圖片描述

explain select age from tbl_user where name like '%aa%';

在這裡插入圖片描述
在這裡插入圖片描述

explain select id from tbl_user where name like '%aa%';   

在這裡插入圖片描述
在這裡插入圖片描述

explain select name from tbl_user where name like '%aa%';  

在這裡插入圖片描述
在這裡插入圖片描述

explain select id, name, age from tbl_user where name like '%aa%';

在這裡插入圖片描述
在這裡插入圖片描述

explain select id, name, age,email from tbl_user where name like '%aa%';   

在這裡插入圖片描述
在這裡插入圖片描述

explain select * from tbl_user where name like '%aa%'; 

在這裡插入圖片描述
在這裡插入圖片描述

9.字串不加單引號索引失效

desc staffs;

在這裡插入圖片描述

name是varchar型別,但是有個值是2000。條件查詢的時候,這個2000的值可以有單引號也可以沒有。接下來我們看兩種情況的區別。

select * from staffs where name = '2000';

在這裡插入圖片描述

select * from staffs where name = 2000;

在這裡插入圖片描述

如果不用單引號,就會把2000從整型自動轉換成字元型。對應上面的第3條規則(不能有隱式的型別轉換)。

explain select * from staffs where name = '2000';

在這裡插入圖片描述

explain select * from staffs where name = 2000;

在這裡插入圖片描述

10.少用or,用它連線時會索引失效

select * from staffs where name = 'July' or name = 'z3';

在這裡插入圖片描述

explain select * from staffs where name = 'July' or name = 'z3';

在這裡插入圖片描述

總結

index(a,b,c)

WHERE語句索引是否被使用
where a = 3Y,使用到 a
where a = 3 and b = 5Y,使用到 a,b
where a = 3 and b = 5 and c = 4Y,使用到 a,b,c
where a = 3 或者 where b = 3 and c = 4 或者 where c = 4N
where a = 3 and c = 5使用到 a,但是 c 不可以,b 中間斷了
where a = 3 and b > 4 and c = 5使用到 a 和 b,c 不能用在範圍之後,b 斷了
where a = 3 and b like ‘kk%’ and c = 4a 能用,b 不能用,c 不能用