MySQL之sql優化
阿新 • • 發佈:2021-02-11
關聯查詢
- 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.使用覆蓋索引。