當(dāng)前位置:首頁 > IT技術(shù) > 數(shù)據(jù)庫 > 正文

數(shù)據(jù)庫sql優(yōu)化總結(jié)之2-百萬級(jí)數(shù)據(jù)庫優(yōu)化方案+案例分析
2021-12-13 17:50:36

目錄

項(xiàng)目背景

7、在 where 子句中使用參數(shù),是不會(huì)導(dǎo)致全表掃描。

案例分析

8、在 where 子句中對(duì)字段進(jìn)行表達(dá)式操作,是不會(huì)導(dǎo)致全表掃描。不過查詢速度會(huì)變慢,所以盡量避免使用。

案例分析

優(yōu)化方案

9、應(yīng)盡量避免在where子句中對(duì)字段進(jìn)行函數(shù)操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。

案例分析

優(yōu)化方案

10.不要在 where 子句中的“=”左邊進(jìn)行函數(shù)、算術(shù)運(yùn)算或其他表達(dá)式運(yùn)算,否則系統(tǒng)將可能無法正確使用索引。

11.在使用索引字段作為條件時(shí),如果該索引是復(fù)合索引,那么必須使用到該索引中的第一個(gè)字段作為條件時(shí)才能保證系統(tǒng)使用該索引,否則該索引將不會(huì)被使用(這個(gè)在mysql中不對(duì)),并且應(yīng)盡可能的讓字段順序與索引順序相一致。

案例分析

12.不要寫一些沒有意義的查詢,如需要生成一個(gè)空表結(jié)構(gòu):(一般開發(fā)也不會(huì)這么無聊啦,在正式的項(xiàng)目上寫這種玩意)


項(xiàng)目背景

有三張百萬級(jí)數(shù)據(jù)表

知識(shí)點(diǎn)表(ex_subject_point)9,316條數(shù)據(jù)

試題表(ex_question_junior)2,159,519條數(shù)據(jù) 有45個(gè)字段

知識(shí)點(diǎn)試題關(guān)系表(ex_question_r_knowledge)3,156,155條數(shù)據(jù)

測試數(shù)據(jù)庫為:mysql (5.7)

?

7、在 where 子句中使用參數(shù),是不會(huì)導(dǎo)致全表掃描。

案例分析

?
?

數(shù)據(jù)庫sql優(yōu)化總結(jié)之2-百萬級(jí)數(shù)據(jù)庫優(yōu)化方案+案例分析_優(yōu)化

8、在 where 子句中對(duì)字段進(jìn)行表達(dá)式操作,是不會(huì)導(dǎo)致全表掃描。不過查詢速度會(huì)變慢,所以盡量避免使用。

案例分析

數(shù)據(jù)庫sql優(yōu)化總結(jié)之2-百萬級(jí)數(shù)據(jù)庫優(yōu)化方案+案例分析_mysql_02

?

執(zhí)行時(shí)間是1.064s

優(yōu)化方案

SELECT ex_question_junior.QUESTION_ID
FROM ex_question_junior 
WHERE ex_question_junior.QUESTION_CHANNEL_TYPE =4/2;
執(zhí)行時(shí)間是0.012s

?

?

?

9、應(yīng)盡量避免在where子句中對(duì)字段進(jìn)行函數(shù)操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。

案例分析

數(shù)據(jù)庫sql優(yōu)化總結(jié)之2-百萬級(jí)數(shù)據(jù)庫優(yōu)化方案+案例分析_數(shù)據(jù)庫優(yōu)化_03

?

優(yōu)化方案

SELECT *
FROM ex_subject_point 
WHERE CREATE_DT >= "2018-05-31"
AND CREATE_DT < "2018-07-01"
但是EXPLAIN一下,發(fā)現(xiàn)這樣還是全表掃描的

數(shù)據(jù)庫sql優(yōu)化總結(jié)之2-百萬級(jí)數(shù)據(jù)庫優(yōu)化方案+案例分析_案例分析_04

?

難道是因?yàn)槿掌谧侄嗡饕龥]有效果嗎?還是因?yàn)橛昧?gt;=和<運(yùn)算符號(hào)?
來驗(yàn)證一下
縮小查詢范圍,發(fā)現(xiàn)索引是有效果的。所以不是日期字段的問題。

數(shù)據(jù)庫sql優(yōu)化總結(jié)之2-百萬級(jí)數(shù)據(jù)庫優(yōu)化方案+案例分析_數(shù)據(jù)庫優(yōu)化_05

換個(gè)字段查詢,用>=和<運(yùn)算符號(hào),索引還是有效果的。但那是什么原因呢?

數(shù)據(jù)庫sql優(yōu)化總結(jié)之2-百萬級(jí)數(shù)據(jù)庫優(yōu)化方案+案例分析_數(shù)據(jù)庫優(yōu)化_06

后來去網(wǎng)上查找了資料,原因是查詢數(shù)量是超過表的一部分,mysql30%,oracle 20%(這個(gè)數(shù)據(jù)可能不準(zhǔn)確,不是官方說明,僅供參考),導(dǎo)致索引失效。
10.不要在 where 子句中的“=”左邊進(jìn)行函數(shù)、算術(shù)運(yùn)算或其他表達(dá)式運(yùn)算,否則系統(tǒng)將可能無法正確使用索引。
例子請(qǐng)看第8點(diǎn)和第9點(diǎn)。
11.在使用索引字段作為條件時(shí),如果該索引是復(fù)合索引,那么必須使用到該索引中的第一個(gè)字段作為條件時(shí)才能保證系統(tǒng)使用該索引,否則該索引將不會(huì)被使用(這個(gè)在mysql中不對(duì)),并且應(yīng)盡可能的讓字段順序與索引順序相一致。

案例分析

復(fù)合索引字段:PATH,PARENT_POINT_ID

數(shù)據(jù)庫sql優(yōu)化總結(jié)之2-百萬級(jí)數(shù)據(jù)庫優(yōu)化方案+案例分析_mysql_07

?

?

?

調(diào)換WHERE子句中的條件順序。發(fā)現(xiàn)還是可以使用索引的

數(shù)據(jù)庫sql優(yōu)化總結(jié)之2-百萬級(jí)數(shù)據(jù)庫優(yōu)化方案+案例分析_案例分析_08

復(fù)合索引只查詢第一個(gè)字段,是有效果的

數(shù)據(jù)庫sql優(yōu)化總結(jié)之2-百萬級(jí)數(shù)據(jù)庫優(yōu)化方案+案例分析_案例分析_09

?

復(fù)合索引只查詢第二個(gè)字段,發(fā)現(xiàn)索引沒有效果了。

數(shù)據(jù)庫sql優(yōu)化總結(jié)之2-百萬級(jí)數(shù)據(jù)庫優(yōu)化方案+案例分析_百萬數(shù)據(jù)優(yōu)化_10

12.不要寫一些沒有意義的查詢,如需要生成一個(gè)空表結(jié)構(gòu):(一般開發(fā)也不會(huì)這么無聊啦,在正式的項(xiàng)目上寫這種玩意)
select col1,col2 into #t from t where 1 = 0
這類代碼不會(huì)返回任何結(jié)果集,但是會(huì)消耗系統(tǒng)資源的,應(yīng)改成這樣:
create table #t(…)

參考:

https://mp.weixin.qq.com/s?__biz=MzIxMjg4NDU1NA==&mid=2247483684&idx=1&sn=f5abc60e696b2063e43cd9ccb40df101&chksm=97be0c01a0c98517029ff9aa280b398ab5c81fa1fcfe0e746222a3bfe75396d9eea1e249af38&mpshare=1&scene=1&srcid=0606XGHeBS4RBZloVv786wBY#rd

***************************************************************************

作者:小虛竹
歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處。
限于本人水平,如果文章和代碼有表述不當(dāng)之處,還請(qǐng)不吝賜教。

?

我不是個(gè)偉大的程序員,我只是個(gè)有著一些優(yōu)秀習(xí)慣的好程序員而己

?

?

?

?

?

本文摘自 :https://blog.51cto.com/u

開通會(huì)員,享受整站包年服務(wù)立即開通 >