1. 程式人生 > 其它 >MySQL之sql優化

MySQL之sql優化

技術標籤:mysqlmysql

關聯查詢

  • left join
    優化規則:在匹配表建立關聯欄位的索引(左側為驅動表,右側有匹配表)。
-- 匹配表不建立索引時,兩張表都是全盤掃描
EXPLAIN SELECT * FROM class LEFT JOIN book ON class.card = book.card;

在這裡插入圖片描述

-- 匹配表關聯欄位建立索引,匹配表只掃描關聯欄位
ALTER TABLE `book` ADD INDEX  idx_card(`card`);
EXPLAIN SELECT * FROM class LEFT JOIN book ON class.card = book.
card ;

在這裡插入圖片描述

  • inner join
    優化規則:同left join,為關聯欄位新增索引。inner join會自動選擇小表作為驅動表。
  • 總結
    1.匹配表的關聯欄位建立索引。
    2.left join或者right join時,選擇小表作為驅動表,因為驅動表會全盤掃描。
    3.子查詢儘可能不放在匹配表,有可能使得索引失效。
    4.能直接關聯表的,就儘可能不使用子查詢。

子查詢

看一個例子:
取所有不為CEO的員工人數,按年齡分組。

-- 子查詢方式,即使子表有索引,也會全盤掃描
CREATE INDEX idx_age_deptid_name ON emp(age,deptid,NAME);
EXPLAIN
SELECT age,COUNT(*) FROM emp WHERE id NOT IN (SELECT ceo FROM dept WHERE ceo IS NOT NULL) GROUP BY age;

在這裡插入圖片描述

-- 為子表ceo欄位建立索引
CREATE INDEX idx_dept_ceo ON dept(ceo);
EXPLAIN SELECT age,COUNT(*) FROM emp WHERE id NOT IN 
	(SELECT ceo FROM dept WHERE ceo IS NOT NULL) GROUP BY age;

在這裡插入圖片描述

-- 用left join 和 is null 代替子查詢not in
EXPLAIN SELECT age,COUNT(*) FROM emp LEFT JOIN dept ON emp.id = dept.ceo WHERE dept.id IS NULL GROUP BY age;

在這裡插入圖片描述
總結:
子查詢為從表關聯欄位建立索引,用left join和is null代替子查詢not in

排序分組

  • 無過濾,不索引
    沒有過濾條件,查詢不使用索引。where和limit都是過濾條件,會使用索引。
CREATE INDEX idx_age_deptid_name ON emp (age,deptid,NAME);
EXPLAIN  SELECT * FROM emp ORDER BY age,deptid;

在這裡插入圖片描述

EXPLAIN SELECT * FROM emp WHERE age=40 ORDER BY deptid;

在這裡插入圖片描述

EXPLAIN  SELECT * FROM emp ORDER BY age,deptid LIMIT 10;

在這裡插入圖片描述

  • 順序錯,必排序
    過濾條件有索引列,查詢才會使用索引。如果索引是複合索引,那麼過濾條件必須包含複合索引的第一列。
    order by後面的順序要和符合索引的順序一致。
-- 可以使用索引且沒有發生手動排序(using filesort)的情況
CREATE INDEX idx_age_deptid_name ON emp (age,deptid,NAME);
EXPLAIN  SELECT * FROM emp WHERE age=45 ORDER BY deptid,NAME;

在這裡插入圖片描述

-- order by後面的順序和複合索引順序不一致,會使用手動排序
explain  select * from emp where age=45 order by  name,deptid;

在這裡插入圖片描述

-- 過濾條件沒有複合索引的第一列
EXPLAIN SELECT * FROM emp WHERE deptid=45 ORDER BY age;

在這裡插入圖片描述

  • 方向反,必排序
    如果排序的方向不一致,也會使用手工排序。
-- 排序方向不一致
explain select * from emp where age=45 order by  deptid asc, name desc ;

在這裡插入圖片描述

-- 排序方向一致
EXPLAIN SELECT * FROM emp WHERE age=45 ORDER BY  deptid DESC, NAME DESC ;

在這裡插入圖片描述

  • goup by同order by
    group by的規則基本上同order by一致。不同的是,group by即使不使用索引欄位過濾,也會使用索引。
EXPLAIN SELECT age FROM emp GROUP BY age;

在這裡插入圖片描述

  • 使用覆蓋索引
    select 和 from之間的查詢欄位<=索引欄位+主鍵。

總結

1.為匹配表關聯欄位建立索引。
2.小表作為驅動表,因為驅動表會進行全盤掃描。
3.匹配表儘可能不使用子查詢。
4.使用left join和is null替換子查詢not in。
5.子查詢為子表的關聯欄位建立索引。
6.查詢儘可能使用過濾條件。
7.order by後面的欄位順序要和複合索引欄位順序一致。
8.order by欄位排序順序要一致。
9.使用覆蓋索引。