初始化測試數據
創建一個測試用的表
create table dept(
id int primary key auto_increment ,
deptName varchar(32) not null unique,
salary decimal(12,6) not null,
remark varchar(256),
createDate date);
在表中插入一萬條數據
BEGIN
Declare i int default 0;
while(i<=10000) do
begin
select i;
set i=i+1;
insert into dept(deptName,salary,createDate,remark) values(i,20000,now(),‘test’);
end ;
End while;
END
通過EXPLAIN分析SQL的執行計劃
type:表示MySQL在表中找到所需行的方式,或者叫訪問類型,常見類型如下(從左到右,性能由差到好)
ALL index range ref eq_ref const,system NULL
ALL: 全表掃描
index: 索引全掃描
range:索引範圍掃描
ref:使用非唯一索引掃描
eq_ref:使用唯一索引掃描
const,system:單表中最多隻有一個匹配行
以上:通過explain分析type是ALL 是性能最差的一種 以下:開始優化。
MySQL中BTREE索引的用法
普通的BTREE索引
優化前 explain select remark from dept where deptName = ?; type ALL
增加索引 ALTER TABLE dept ADD INDEX index_remark (remark
);
優化測試 explain select remark from dept where deptName = ?; type ref
聯合BTREE索引
增加聯合索引 ALTER TABLE dept ADD INDEX index_all (deptName
,remark
,createDate
);
explain select deptName,remark,createDate from dept where deptName=‘2’ and remark = 'test’and createDate =‘2018-07-22’;—— type ref
但是explain select deptName,remark,createDate from dept where remark = 'test’and createDate =‘2018-07-22’; ——type index
——type從ref(使用非唯一索引掃描)變成了index(索引全掃描),
上面兩個SQL 索引相同 Type不同是因爲 BTREE索引中匹配最左前綴 比如給col1+col2+col3字段上加聯合索引能夠被包含col1+col2 、col1+col2+col3、col1+col3使用(順序沒有影響 比如 where col1=? and col2=? 和 where col2=? and col1=? 結果一樣)
使用聯合索引 相當於一下子創建瞭如上的三個索引,這就是聯合索引的好處
存在索引但不能使用索引的經典場景
例句:explain select deptName,remark,createDate from dept where deptName=‘2’ and remark = 'test’and createDate =‘2018-07-22’;
——type ref
下面是反面教材:
1.以%開頭的LIKE查詢不能使用BTREE索引
explain select deptName,remark,createDate from dept where deptName like’%2’ and remark = 'test’and createDate =‘2018-07-22’; type index
2.數據類型出現隱式轉換時也不能使用索引
explain select deptName,remark,createDate from dept where deptName =2 and remark = 'test’and createDate =‘2018-07-22’; type index
3.複合索引時 不符合最左匹配原則(上面已經提到)
explain select deptName,remark,createDate from dept where remark = 'test’and createDate =‘2018-07-22’; type index
4.用or分隔開的條件,如果or前的條件中的列有索引,後面的列中沒有索引,那麼涉及到的索引都不會使用到
explain select deptName,remark,createDate from dept where deptName =‘2’ and remark = 'test’and createDate =‘2018-07-22’ or salary =200; type ALL
Order By語句
order by 字段混合使用DESC ASC 不會使用索引
select * from table order by key1 desc,key2 asc (儘量不要出現這種混合排序)
Where條件過濾的關鍵字和Order by中所使用的不同 不會使用索引
select * from table where key2 = ? order by key1 (order by 出現的關鍵字 儘量 在where條件中也出現)
優化Group By語句
當我們的SQL語句需要Group By分組時:
explain分析SQL的時候 Extra那一列有時候會出現 using Filesort表示需要額外的排序 如果業務沒有要求排序 我們可以通過禁止排序, 加上 Order By NULL 有時候可以去掉using filesort
MySQL應不應該加唯一約束和外鍵約束
外鍵約束可以通過代碼控制,加起來開發很不方便不建議加。如果業務需要唯一約束,因爲唯一約束代碼很難控制,必須加
對於唯一約束,有人說先查出來數據庫已經存在的 再去判斷傳值存不存在。這樣的缺點 1.查詢所有已經存在的很費時間,2.需要考慮併發 不然重複數據還是會進入到數據庫
一旦進入了錯誤數據 以後想加唯一約束都加不上了
查詢語句關鍵字使用順序: WHERE GROUP BY HAVING ORDER BY DESC LIMIT
補充
唯一索引
explain select deptName,remark,createDate from dept where id=2; type const 像這種利用唯一索引做where條件的效率最高 (主鍵默認被加上了唯一索引)
SQL表連接查詢時 表連接的條件(也就是外鍵)必須加索引(阿里巴巴代碼規範看到的)
重要: 多表連接的時候 join on(a.id=b.id2) 連接外鍵id、id2 必須加索引。MySQL規定作爲外鍵的字段必須有索引 也是爲了讓我們表連接的時候 用到索引(其實做到這點 基本上足夠優化百分之八十的SQL了)