常見的十種SQL語句性能優(yōu)化策略詳解
SQL語句性能優(yōu)化策略
1. 為 WHERE 及 ORDER BY 涉及的列上建立索引
對查詢進(jìn)行優(yōu)化,應(yīng)盡量避免全表掃描,首先應(yīng)考慮在 WHERE 及 ORDER BY 涉及的列上建立索引
2. where中使用默認(rèn)值代替null
應(yīng)盡量避免在 WHERE 子句中對字段進(jìn)行 NULL 值判斷,創(chuàng)建表時(shí) NULL 是默認(rèn)值,但大多數(shù)時(shí)候應(yīng)該使用 NOT NULL,或者使用一個(gè)特殊的值,如 0,-1 作為默認(rèn)值。
為啥建議where中使用默認(rèn)值代替null,四個(gè)原因:
- 并不是說使用了is null或者 is not null就會(huì)不走索引了,這個(gè)跟mysql版本以及查詢成本都有關(guān);
- 如果mysql優(yōu)化器發(fā)現(xiàn),走索引比不走索引成本還要高,就會(huì)放棄索引,這些條件 !=,<>,is null,is not null經(jīng)常被認(rèn)為讓索引失效;
- 其實(shí)是因?yàn)橐话闱闆r下,查詢的成本高,優(yōu)化器自動(dòng)放棄索引的;
- 如果把null值,換成默認(rèn)值,很多時(shí)候讓走索引成為可能,同時(shí),表達(dá)意思也相對清晰一點(diǎn);
3. 慎用 != 或 <> 操作符
MySQL 只有對以下操作符才使用索引:<,<=,=,>,>=,BETWEEN,IN,以及某些時(shí)候的 LIKE。所以:應(yīng)盡量避免在 WHERE 子句中使用 != 或 <> 操作符, 會(huì)導(dǎo)致全表掃描。
4. 慎用 OR 來連接條件
使用or可能會(huì)使索引失效,從而全表掃描; 應(yīng)盡量避免在 WHERE 子句中使用 OR 來連接條件,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。
5. 慎用 IN 和 NOT IN
IN 和 NOT IN 也要慎用,否則會(huì)導(dǎo)致全表掃描。對于連續(xù)的數(shù)值,能用 BETWEEN 就不要用 IN:select id from t where num between 1 and 3。
6. 慎用 左模糊like ‘%…’
模糊查詢,程序員最喜歡的就是使用like,like很可能讓索引失效。比如:
select id from t where name like‘%abc%' select id from t where name like‘%abc'
而select id from t where name like‘abc%’才用到索引。 所以:
- 首先盡量避免模糊查詢,如果必須使用,不采用全模糊查詢,也應(yīng)盡量采用右模糊查詢, 即like ‘…%’,是會(huì)使用索引的;
- 左模糊like ‘%…’無法直接使用索引,但可以利用reverse + function index的形式,變化成 like ‘…%’;
- 全模糊查詢是無法優(yōu)化的,一定要使用的話建議使用搜索引擎,比如 ElasticSearch。
7. WHERE條件使用參數(shù)會(huì)導(dǎo)致全表掃描
如下面語句將進(jìn)行全表掃描:
select id from t where num=@num
因?yàn)镾QL只有在運(yùn)行時(shí)才會(huì)解析局部變量,但優(yōu)化程序不能將訪問計(jì)劃的選擇推 遲到 運(yùn)行時(shí);
它必須在編譯時(shí)進(jìn)行選擇。然而,如果在編譯時(shí)建立訪問計(jì)劃,變量的值還是未知的,因而無法作為索引選擇的輸入項(xiàng)。
所以, 可以改為強(qiáng)制查詢使用索引:
select id from t with(index(索引名)) where num=@num
8. 應(yīng)避免WHERE 表達(dá)式操作/對字段進(jìn)行函數(shù)操作
任何對列的操作都將導(dǎo)致表掃描,它包括數(shù)據(jù)庫函數(shù)、計(jì)算表達(dá)式等等, 應(yīng)盡量避免在 WHERE 子句中對字段進(jìn)行表達(dá)式操作,應(yīng)盡量避免在 WHERE 子句中對字段進(jìn)行函數(shù)操作。
如:
select id from t where num/5=100 應(yīng)改為: select id from t where num=100*5
應(yīng)盡量避免在where子句中對字段進(jìn)行函數(shù)操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。 如:
select id from t where substring(name,1,3)=‘a(chǎn)bc' select id from t where datediff(day,createdate,‘2022-11-30')=0 應(yīng)改為: select id from t where name like ‘a(chǎn)bc%' select id from t where createdate>=‘2022-11-30' and createdate<‘2022-12-1'
9. 用 EXISTS 代替 IN 是一個(gè)好的選擇
很多時(shí)候用exists 代替in 是一個(gè)好的選擇
select num from a where num in(select num from b) 用下面的語句替換: select num from a where exists(select 1 from b where num=a.num)
10. 查詢SQL盡量不要使用select *,而是具體字段
最好不要使用返回所有:select * from t ,用具體的字段列表代替 “*”,不要返回用不到的任何字段。select *的弊端:
(1)增加很多不必要的消耗,比如CPU、IO、內(nèi)存、網(wǎng)絡(luò)帶寬;
(2)增加了使用覆蓋索引的可能性;
(3)增加了回表的可能性;
(4)當(dāng)表結(jié)構(gòu)發(fā)生變化時(shí),前端也需要更改;
(5)查詢效率低;
到此這篇關(guān)于常見的十種SQL語句性能優(yōu)化策略詳解的文章就介紹到這了,更多相關(guān)SQL語句性能優(yōu)化策略內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mysql where中如何判斷不為空的實(shí)現(xiàn)
本文主要介紹了mysql where中如何判斷不為空的實(shí)現(xiàn),本文將針對這些空演示如何判斷是否為空,以及如何寫sql過濾,包括使用判空函數(shù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-03-03
mysql8.0及以上my.cnf設(shè)置lower_case_table_names=1無法啟動(dòng)問題
這篇文章主要介紹了mysql8.0及以上my.cnf設(shè)置lower_case_table_names=1無法啟動(dòng)問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
mysql數(shù)據(jù)備份與恢復(fù)實(shí)現(xiàn)方法分析
這篇文章主要介紹了mysql數(shù)據(jù)備份與恢復(fù)實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了mysql數(shù)據(jù)備份與恢復(fù)常見實(shí)現(xiàn)方法與相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2020-04-04
詳細(xì)解讀分布式鎖原理及三種實(shí)現(xiàn)方式
這篇文章從三種基于不同形式的分布式鎖的實(shí)現(xiàn),數(shù)據(jù)庫、緩存和zookeeper,內(nèi)容比較詳細(xì),具有一定參考價(jià)值,需要的朋友可以了解下。2017-10-10
MySQL 中只統(tǒng)計(jì)周一到周五的到訪數(shù)據(jù)(案例演示)
文章介紹了如何在醫(yī)院信息系統(tǒng)中高效統(tǒng)計(jì)工作日到訪人數(shù),避免全表掃描和索引失效的問題,通過生成列和使用日期維表,可以實(shí)現(xiàn)快速查詢和報(bào)表分析,適用于大型醫(yī)院的復(fù)雜數(shù)據(jù)量,感興趣的朋友跟隨小編一起看看吧2025-12-12
MySql Error 1698(28000)問題的解決方法
這篇文章主要介紹了MySql Error 1698(28000)問題的解決方法,需要的朋友可以參考下2017-06-06

