hjr-SQL-語句的優化

語句分析

首先在查詢語句前面加上explain

然後看type 列,是索引生效的不同類型

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

儘量往上優化

沒索引的加上索引

索引在join on上一般都是 all

儘量在where上加上條件,某些寫法會導致索引失效,或者降低到all,自己多嘗試

rows 是必須檢查的行數 越少越好

寫法

把每個表自身的where條件查詢結果寫到一個括號裏,查詢後再join
和先join 再統一通過表的別名 where 去查詢 沒區別

運算

某些每join一次查詢都會做的運算,可以移動到代碼裏,直接傳一個固定值到sql中

批量

當for循環裏面有插入或刪除操作,可以先建一個list,然後放到for循環外面批量插入

where和on的區別

left join where和on有區別

inner join 沒區別

當條件放在on後面時,無論on條件的真假,都會返回左表的值;

當條件放在where後面時,只有滿足條件的記錄會返回。

where 查詢速度快 on慢 where返回數據少 on多

比如 學生表a 和分數表b

學生有字段 姓名 年齡 分數有 學科 分數

left join 後相當於一個新表c 擁有字段 姓名 年齡 學科 分數四個字段

如果查詢條件寫到where後,那麼相當於對c表做篩選,

比如同樣的學科爲數學作爲篩選條件

現在學生表有3條數據,分數表有2條數據(一條語文,一條數學)

如果我們左連接不做條件篩選那麼會得到3條數據

如果我們把篩選條件寫到on後面了也是三條,因爲相當於先對錶b做篩選,現在表a有三條,表b有一條,左連接後表c有三條數據

但是如果寫到where後,原本表c應該是三條,但是要對錶c做一個篩選,學科爲數學,所以最後表c只有一條數據了

根據業務拆分

比如一個用戶表 一個訂單表

先查詢用戶數據

10 條,然後for遍歷 這10條 然後 in 查詢訂單表

代替 用戶表left join 訂單表

派生表

雖然派生表不走索引速度慢,但是當有查詢條件時只能用派生表

加篩選條件必須做派生表 條件寫到後面

否則 寫到 where後面 會影響join的結果

比如 用戶 有 3個訂單 1,2,3 返回的列表應該是用戶 有 (1,2,3)訂單

現在篩選條件是訂單等於1 如果寫到where後面

最後返回的列表會 (1)

如果先join查詢出 用戶 擁有的訂單爲(1,2,3)

再篩選條件是訂單等於1 返回的用戶列表是 訂單爲(1,2,3)

並且不用派生表 select * from (select sum(a) as ss left join… where sum(a)>xx) as table where ss >xx

只能這麼寫條件
sum(a)>xx

用了派生表可以這麼寫條件
ss >xx

不過數據量達到百萬級使用派生錶速度大概要慢5s,所以篩選條件的複雜度決定要不要用派生表

on條件移動到where

on後面的and條件比在where後慢很多

但是不放到on後面有時會導致返回數據變少

但是當某些特定條件下,依舊可以把on後面的條件放到where後面

比如 對某些特定篩選條件單獨寫一個sql的優化,

只有2個表,a左連接b,on後面的條件肯定能命中非Null數據

這個條件放到on後面或者where後都無所謂的情況

count(*)的優化

select count(*) from(select * from where xxx group by x) as xx

可以改爲

select count(distinct x) as num where xxx 去掉group by

具體某個條件的優化

比如查詢學生分數,條件是入學日期,其他的查詢條件速度都很快,就這一個慢,我們可以把這個條件單獨寫一個sql,然後不同的查詢條件走不同的sql

表做冗餘

如果a左連接b表,a和b表數據都很多,可以先給a表做冗餘字段,然後定時清洗b的數據到a的字段裏

排序

當備註欄裏面有filesort的時候就需要對排序優化爲index sort

如果沒有排序需求 還group by了,需要在group by後面加上order null 這樣可以去掉filesort因爲會自動對group by排序

當需要排序的時候,可以試着
建立組合索引,滿足最左生效原則
或者把group by給去掉

或者把group by的條件和order by設置成一樣的

多個排序條件不要一個desc 一個asc的 要保持一個方向

字符集索引失效

SHOW FULL COLUMNS FROM tabelName
有時on 條件索引莫名失效
查看字符集看條件字段是否是同一個編碼

不是的話修改爲統一編碼
alter table <表名> change <字段名> <字段名> <類型> CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章