mysql優(yōu)化學(xué)習(xí)

1.高并發(fā)優(yōu)化點(diǎn)有:

如果請求過多,判定web服務(wù)器的壓力過大,增加前端的web服務(wù)器,做負(fù)載均衡

如果請求靜態(tài)界面不卡了,但是動(dòng)態(tài)數(shù)據(jù)還是卡,說明MySQL處理的請求太多了,在應(yīng)用層增加緩存.

數(shù)據(jù)庫層其實(shí)是最脆弱的一層啡省,一般在應(yīng)用設(shè)計(jì)時(shí)在上游就需要把請求攔截掉娜睛,數(shù)據(jù)庫層只承擔(dān)“能力范圍內(nèi)”的訪問請求髓霞,所以,我們通過在服務(wù)層引入隊(duì)列和緩存畦戒,讓最底層的數(shù)據(jù)庫高枕無憂方库。但是如果請求激增,還是有大量的查詢壓力到MySQL,這個(gè)時(shí)候就要想辦法解決MySQL的瓶頸了。

2.mysql執(zhí)行流程:

大致可以分為以下步驟:

1.當(dāng)我們請求mysql服務(wù)器的時(shí)候,MySQL前端會有一個(gè)監(jiān)聽,請求到了之后,服務(wù)器得到相關(guān)的SQL語句,執(zhí)行之前(虛線部分為執(zhí)行),還會做權(quán)限的判斷

2.通過權(quán)限之后,SQL就到MySQL內(nèi)部,他會在查詢緩存中,看該SQL有沒有執(zhí)行過,如果有查詢過,則把緩存結(jié)果返回,說明在MySQL內(nèi)部,也有一個(gè)查詢緩存.但是這個(gè)查詢緩存,默認(rèn)是不開啟的,這個(gè)查詢緩存,和我們的Hibernate障斋,Mybatis的查詢緩存是一樣的,因?yàn)椴樵兙彺嬉骃QL和參數(shù)都要一樣,所以這個(gè)命中率是非常低的纵潦。

3.如果我們沒有開啟查詢緩存,或者緩存中沒有找到對應(yīng)的結(jié)果,那么就到了解析器,解析器主要對SQL語法進(jìn)行解析

4.解析結(jié)束后就變成一顆解析樹,這個(gè)解析樹其實(shí)在Hibernate里面也是有的,大家回憶一下,在以前做過Hibernate項(xiàng)目的時(shí)候,是不是有個(gè)一個(gè)antlr.jar。這個(gè)就是專門做語法解析的工具.因?yàn)樵贖ibernate里面有HQL垃环,它就是通過這個(gè)工具轉(zhuǎn)換成SQL的,我們編程語言之所以有很多規(guī)范邀层、語法,其實(shí)就是為了便于這個(gè)解析器解析,這個(gè)學(xué)過編譯原理的應(yīng)該知道.

5.得到解析樹之后,不能馬上執(zhí)行,這還需要對這棵樹進(jìn)行預(yù)處理,也就是說,這棵樹,我沒有經(jīng)過任何優(yōu)化的樹,預(yù)處理器會這這棵樹進(jìn)行一些預(yù)處理,比如常量放在什么地方,如果有計(jì)算的東西,把計(jì)算的結(jié)果算出來等等...

6.預(yù)處理完畢之后,此時(shí)得到一棵比較規(guī)范的樹,這棵樹就是要拿去馬上做執(zhí)行的樹,比起之前的那棵樹,這棵得到了一些優(yōu)化的解析樹

7.查詢優(yōu)化器,是MySQL里面最關(guān)鍵的東西,我們寫任何一條SQL,比如SELECT * FROM USER WHERE USERNAME = toby AND PASSWORD = 1,它會怎么去執(zhí)行?它是先執(zhí)行username = toby還是password = 1?每一條SQL的執(zhí)行順序查詢優(yōu)化器就是根據(jù)MySQL對數(shù)據(jù)統(tǒng)計(jì)表的一些信息,比如索引,比如表一共有多少數(shù)據(jù),MySQL都是有緩存起來的,在真正執(zhí)行SQL之前,他會根據(jù)自己的這些數(shù)據(jù),進(jìn)行一個(gè)綜合的判定,判斷這一次在多種執(zhí)行方式里面,到底選哪一種執(zhí)行方式,可能運(yùn)行的最快.這一步是MySQL性能中,最關(guān)鍵的核心點(diǎn),也是我們的優(yōu)化原則.我們平時(shí)所講的優(yōu)化SQL,其實(shí)說白了,就是想讓查詢優(yōu)化器,按照我們的想法,幫我們選擇最優(yōu)的執(zhí)行方案,因?yàn)槲覀儽萂ySQL更懂我們的數(shù)據(jù).MySQL看數(shù)據(jù),僅僅只是自己收集到的信息,這些信息可能是不準(zhǔn)確的,MySQL根據(jù)這些信息選了一個(gè)它自認(rèn)為最優(yōu)的方案,但是這個(gè)方案可能和我們想象的不一樣.

8.這里的查詢執(zhí)行計(jì)劃,也就是MySQL查詢中的執(zhí)行計(jì)劃,比如要先執(zhí)行username = toby還是password = 1

9.這個(gè)執(zhí)行計(jì)劃會傳給查詢執(zhí)行引擎,執(zhí)行引擎選擇存儲引擎來執(zhí)行這一份傳過來的計(jì)劃,到磁盤中的文件中去查詢,這個(gè)時(shí)候重點(diǎn)來了,影響這個(gè)查詢性能最根本的原因是什么?就是硬盤的機(jī)械運(yùn)動(dòng),也就是我們平時(shí)熟悉的IO,所以一條查詢語句是快還是慢,就是根據(jù)這個(gè)時(shí)間的IO來確定的.那怎么執(zhí)行IO又是什么來確定的?就是傳過來的這一份執(zhí)行計(jì)劃.

10.如果開了查詢緩存,則返回結(jié)果給客戶端,并且查詢緩存也放一份遂庄。



#要提高M(jìn)ySQL的更新/插入效率被济,應(yīng)首先考慮降低鎖的競爭,減少寫操作的等待時(shí)間

3.增刪改查

一涧团、INSERT語句:

基本:INSERT [INTO] 表名 [(字段列表)] VALUES (值列表)[, (值列表), …]

注意:

如果要插入的值列表包含所有字段并且順序一致只磷,則可以省略字段列表。

可同時(shí)插入多條數(shù)據(jù)記錄泌绣!

REPLACE 與 INSERT 完全一樣钮追,可互換。

優(yōu)化前例子:

優(yōu)化策略:

(1)當(dāng)我們需要批量插入數(shù)據(jù)的時(shí)候阿迈,這樣的語句卻會出現(xiàn)性能問題元媚。例如說,如果有需要插入100000條數(shù)據(jù)苗沧,那么就需要有100000條insert語句刊棕,每一句都需要提交到關(guān)系引擎那里去解析,優(yōu)化待逞,然后才能夠到達(dá)存儲引擎做真的插入工作甥角。上述所說的同時(shí)插入多條就是一種優(yōu)化。(經(jīng)測試识樱,大概10條同時(shí)插入是最高效的)

優(yōu)化后例子:

(2)將進(jìn)程/線程數(shù)控制在2倍于CPU數(shù)目相對合適

(3)采用順序主鍵策略(例如自增主鍵嗤无,或者修改業(yè)務(wù)邏輯,讓插入的記錄盡可能順序主鍵)

(4)考慮使用replace 語句代替insert語句怜庸。(REPLACE語句請參考下文当犯,有詳細(xì)講述)

二、DELETE語句:

DELETE FROM 表名[ 刪除條件子句](沒有條件子句割疾,則會刪除全部)

例子:

補(bǔ)充:Mysql中的truncate table和delete語句都可以刪除表里面所有數(shù)據(jù)嚎卫,但是在一些情況下有些不同!

例子:

truncate table gag;

(1)truncate table刪除速度更快宏榕,拓诸,但truncate table刪除后不記錄mysql日志胸懈,不可以恢復(fù)數(shù)據(jù)。(謹(jǐn)慎使用)

(2)如果沒有外鍵關(guān)聯(lián)恰响,innodb執(zhí)行truncate是先drop table(原始表),再創(chuàng)建一個(gè)跟原始表一樣空表,速度要遠(yuǎn)遠(yuǎn)快于delete逐條刪除行記錄趣钱。

(3)如果使用innodb_file_per_table參數(shù)烙丛,truncate table 能重新利用釋放的硬盤空間,在InnoDB Plugin中政己,truncate table為自動(dòng)回收,如果不是用InnoDB Plugin,那么需要使用optimize table來優(yōu)化表俏橘,釋放空間枢劝。

truncate table刪除表后井联,optimize table尤其重要,特別是大數(shù)據(jù)數(shù)據(jù)庫您旁,表空間可以得到釋放烙常!

(4)表有外鍵關(guān)聯(lián),truncate table刪除表數(shù)據(jù)為逐行刪除鹤盒,如果外鍵指定級聯(lián)刪除(delete cascade)蚕脏,關(guān)聯(lián)的子表也會會被刪除所有表數(shù)據(jù)。如果外鍵未指定級聯(lián)(cascde),truncate table逐行刪除數(shù)據(jù)侦锯,如果是父行關(guān)聯(lián)子表行數(shù)據(jù)驼鞭,將會報(bào)錯(cuò)。

注意:

一個(gè)大的 DELETE 或 INSERT 操作尺碰,要非常小心挣棕,因?yàn)檫@兩個(gè)操作是會鎖表的,表一鎖住亲桥,其他操作就進(jìn)不來了洛心。因此,我們要交給DBA去拆分题篷,重整數(shù)據(jù)庫策略词身,比如限制處理1000條。

另外悼凑,擴(kuò)展下刪除和索引的聯(lián)系偿枕,由于索引需要額外的維護(hù)成本;因?yàn)樗饕募菃为?dú)存在的文件,所以當(dāng)我們對數(shù)據(jù)的增加,修改,刪除,都會產(chǎn)生額外的對索引文件的操作,這些操作需要消耗額外的IO,會降低增/改/刪的執(zhí)行效率户辫。所以,在我們刪除數(shù)據(jù)庫百萬級別數(shù)據(jù)的時(shí)候嗤锉,查詢MySQL官方手冊得知?jiǎng)h除數(shù)據(jù)的速度和創(chuàng)建的索引數(shù)量是成正比的渔欢。所以我們想要?jiǎng)h除百萬數(shù)據(jù)的時(shí)候可以先刪除索引(此時(shí)大概耗時(shí)三分多鐘),然后刪除其中無用數(shù)據(jù)瘟忱,此過程需要不到兩分鐘奥额,刪除完成后重新創(chuàng)建索引(此時(shí)數(shù)據(jù)較少了)創(chuàng)建索引也非成淮保快,約十分鐘左右垫挨。與之前的直接刪除絕對是要快速很多韩肝,更別說萬一刪除中斷,一切刪除會回滾。那更是坑了九榔。

三哀峻、UPDATE語句:

UPDATE 表名 SET 字段名=新值[, 字段名=新值] [更新條件]

例子:

優(yōu)化:更新多條記錄(往后會結(jié)合MyBatics寫個(gè)實(shí)例)

更新多條記錄的多個(gè)值

(1). 盡量不要修改主鍵字段。(廢話哲泊,反正我就從沒改過..)

(2). 當(dāng)修改VARCHAR型字段時(shí)剩蟀,盡量使用相同長度內(nèi)容的值代替。

(3). 盡量最小化對于含有UPDATE觸發(fā)器的表的UPDATE操作切威。

(4). 避免UPDATE將要復(fù)制到其他數(shù)據(jù)庫的列育特。

(5). 避免UPDATE建有很多索引的列。

(6). 避免UPDATE在WHERE子句條件中的列先朦。

四缰冤、REPLACE語句:

根據(jù)應(yīng)用情況可以使用replace 語句代替insert/update語句。例如:如果一個(gè)表在一個(gè)字段上建立了唯一索引喳魏,當(dāng)向這個(gè)表中使用已經(jīng)存在的鍵值插入一條記錄锋谐,將會拋出一個(gè)主鍵沖突的錯(cuò)誤。如果我們想用新記錄的值來覆蓋原來的記錄值時(shí)截酷,就可以使用REPLACE語句涮拗。

使用REPLACE插入記錄時(shí),如果記錄不重復(fù)(或往表里插新記錄)迂苛,REPLACE功能與INSERT一樣三热,如果存在重復(fù)記錄,REPLACE就使用新記錄的值來替換原來的記錄值三幻。使用REPLACE的最大好處就是可以將DELETE和INSERT合二為一就漾,形成一個(gè)原子操作。這樣就可以不必考慮同時(shí)使用DELETE和INSERT時(shí)添加事務(wù)等復(fù)雜操作了念搬。

在使用REPLACE時(shí)抑堡,表中必須有唯一有一個(gè)PRIMARY KEY或UNIQUE索引,否則朗徊,使用一個(gè)REPLACE語句沒有意義首妖。

用法:

(1)同INSERT

含義一:與普通INSERT一樣功能

REPLACE INTO score (change_type,score,user_id) VALUES ('吃飯',10,1),('喝茶',10,1),('喝茶',10,1);

含義二:找到第一條記錄,用后面的值進(jìn)行替換

REPLACE INTO score (id,change_type,score,user_id) VALUES (1,'吃飯',10,1)

此語句的作用是向表table中插入3條記錄爷恳。如果主鍵id為1或2不存在就相當(dāng)于插入語句:

INSERT INTO score (change_type,score,user_id) VALUES (‘吃飯’,10,1),(‘喝茶’,10,1),(‘喝茶’,10,1);

如果存在相同的值則不會插入數(shù)據(jù)有缆。

(2)replace(object, search, replace),把object中出現(xiàn)search的全部替換為replace。

用法一:并不是修改數(shù)據(jù)棚壁,而只是單純做局部替換數(shù)據(jù)返還而已杯矩。

SELECT REPLACE('喝茶','茶','喝')//結(jié)果: 喝喝123

用法二:修改表數(shù)據(jù)啦,對應(yīng)下面就是袖外,根據(jù)change_type字段找到做任務(wù)的數(shù)據(jù)史隆,用bb來替換

UPDATE score SET change_type=REPLACE(change_type,'做任務(wù)','bb')1

在此,做下對比:UPDATE和REPLACE的區(qū)別:

1)UPDATE在沒有匹配記錄時(shí)什么都不做曼验,而REPLACE在有重復(fù)記錄時(shí)更新泌射,在沒有重復(fù)記錄時(shí)插入。

2)UPDATE可以選擇性地更新記錄的一部分字段蚣驼。而REPLACE在發(fā)現(xiàn)有重復(fù)記錄時(shí)就將這條記錄徹底刪除魄幕,再插入新的記錄。也就是說颖杏,將所有的字段都更新了纯陨。

其實(shí)REPLACE更像INSERT與DELETE的結(jié)合。


單表查詢優(yōu)化

(0)可以先使用EXPLAIN關(guān)鍵字可以讓你知道MySQL是如何處理你的SQL語句的留储。這可以幫我們分析是查詢語句或是表結(jié)構(gòu)的性能瓶頸翼抠。

(1)寫sql要明確需要的字段,要多少就寫多少字段获讳,而不是濫用 select *

(2)可以用使用連接(JOIN)來代替子查詢

(3)使用分頁語句:limit start , count 或者條件 where子句時(shí)阴颖,有什么可限制的條件盡量加上,查一條就limit一條丐膝。做到不濫用量愧。比如說我之前做過的的p2p項(xiàng)目,只是需要知道有沒有一個(gè)滿標(biāo)的借款,這樣的話就可以用上 limit 1帅矗,這樣mysql在找到一條數(shù)據(jù)后就停止搜索偎肃,而不是全文搜索完再停止。

(4)開啟查詢緩存:

大多數(shù)的MySQL服務(wù)器都開啟了查詢緩存浑此。這是提高查詢有效的方法之一累颂。當(dāng)有很多相同的查詢被執(zhí)行了多次的時(shí)候,這些查詢結(jié)果會被放到一個(gè)緩存中凛俱,這樣紊馏,后續(xù)的相同的查詢就不用操作表而直接訪問緩存結(jié)果了。

查詢緩存工作流程:

A):服務(wù)器接收SQL蒲犬,以SQL+DB+Query_cache_query_flags作為hash查找鍵朱监;

B):找到了相關(guān)的結(jié)果集就將其返回給客戶端;

C):如果沒有找到緩存則執(zhí)行權(quán)限驗(yàn)證暖哨、SQL解析赌朋、SQL優(yōu)化等一些列的操作凰狞;

D):執(zhí)行完SQL之后篇裁,將結(jié)果集保存到緩存

當(dāng)然沛慢,并不是每種情況都適合使用緩存,衡量打開緩存是否對系統(tǒng)有性能提升是一個(gè)整體的概念达布。那怎么判斷要不要開啟緩存呢团甲,如下:

1)通過緩存命中率判斷, 緩存命中率 = 緩存命中次數(shù) (Qcache_hits) / 查詢次數(shù) (Com_select)、

2)通過緩存寫入率, 寫入率 = 緩存寫入次數(shù) (Qcache_inserts) / 查詢次數(shù) (Qcache_inserts)

3)通過 命中-寫入率 判斷, 比率 = 命中次數(shù) (Qcache_hits) / 寫入次數(shù) (Qcache_inserts), 高性能MySQL中稱之為比較能反映性能提升的指數(shù),一般來說達(dá)到3:1則算是查詢緩存有效,而最好能夠達(dá)到10:1

相關(guān)參數(shù)及命令:

與緩存相關(guān)的主要參數(shù)如下表所示黍聂√煽啵可以使用命令SHOW VARIABLES LIKE '%query_cache%'查看

緩存數(shù)據(jù)失效時(shí)機(jī)

在表的結(jié)構(gòu)或數(shù)據(jù)發(fā)生改變時(shí),查詢緩存中的數(shù)據(jù)不再有效产还。有這些INSERT匹厘、UPDATE、 DELETE脐区、TRUNCATE愈诚、ALTER TABLE、DROP TABLE或DROP DATABASE會導(dǎo)致緩存數(shù)據(jù)失效牛隅。所以查詢緩存適合有大量相同查詢的應(yīng)用炕柔,不適合有大量數(shù)據(jù)更新的應(yīng)用。

可以使用下面三個(gè)SQL來清理查詢緩存:

1媒佣、FLUSH QUERY CACHE; // 清理查詢緩存內(nèi)存碎片匕累。

2、RESET QUERY CACHE; // 從查詢緩存中移出所有查詢默伍。

3欢嘿、FLUSH TABLES; //關(guān)閉所有打開的表,同時(shí)該操作將會清空查詢緩存中的內(nèi)容也糊。

InnoDB與查詢緩存:

Innodb會對每個(gè)表設(shè)置一個(gè)事務(wù)計(jì)數(shù)器,里面存儲當(dāng)前最大的事務(wù)ID.當(dāng)一個(gè)事務(wù)提交時(shí),InnoDB會使用MVCC中系統(tǒng)事務(wù)ID最大的事務(wù)ID跟新當(dāng)前表的計(jì)數(shù)器.

只有比這個(gè)最大ID大的事務(wù)能使用查詢緩存,其他比這個(gè)ID小的事務(wù)則不能使用查詢緩存.

另外,在InnoDB中,所有有加鎖操作的事務(wù)都不使用任何查詢緩存

(MVCC (Multiversion Concurrency Control)炼蹦,即多版本并發(fā)控制技術(shù),它使得大部分支持行鎖的事務(wù)引擎,不再單純的使用行鎖來進(jìn)行數(shù)據(jù)庫的并發(fā)控制显设,取而代之的是把數(shù)據(jù)庫的行鎖與行的多個(gè)版本結(jié)合起來框弛,只需要很小的開銷,就可以實(shí)現(xiàn)非鎖定讀,從而大大提高數(shù)據(jù)庫系統(tǒng)的并發(fā)性能)

多表查詢連接的選擇:

相信這內(nèi)連接捕捂,左連接什么的大家都比較熟悉了瑟枫,當(dāng)然還有左外連接什么的,基本用不上我就不貼出來了指攒。這圖只是讓大家回憶一下慷妙,各種連接查詢。 然后要告訴大家的是允悦,需要根據(jù)查詢的情況膝擂,想好使用哪種連接方式效率更高。

二、MySQL的JOIN實(shí)現(xiàn)原理

在MySQL 中架馋,只有一種Join 算法狞山,就是大名鼎鼎的Nested Loop Join,他沒有其他很多數(shù)據(jù)庫所提供的Hash Join叉寂,也沒有Sort Merge Join萍启。顧名思義,Nested Loop Join 實(shí)際上就是通過驅(qū)動(dòng)表的結(jié)果集作為循環(huán)基礎(chǔ)數(shù)據(jù)屏鳍,然后一條一條的通過該結(jié)果集中的數(shù)據(jù)作為過濾條件到下一個(gè)表中查詢數(shù)據(jù)勘纯,然后合并結(jié)果。如果還有第三個(gè)參與Join钓瞭,則再通過前兩個(gè)表的Join 結(jié)果集作為循環(huán)基礎(chǔ)數(shù)據(jù)驳遵,再一次通過循環(huán)查詢條件到第三個(gè)表中查詢數(shù)據(jù),如此往復(fù)山涡。 ——摘自《MySQL 性能調(diào)優(yōu)與架構(gòu)設(shè)計(jì)》

三堤结、補(bǔ)充:mysql對sql語句的容錯(cuò)問題

即在sql語句不完全符合書寫建議的情況,mysql會允許這種情況佳鳖,盡可能解釋它:

1)一般cross join后面加上where條件霍殴,但是用cross join+on也是被解釋為cross join+where

2)一般內(nèi)連接都需要加上on限定條件系吩,如上面場景一来庭;如果不加會被解釋為交叉連接;

3)如果連接表格使用的是逗號穿挨,會被解釋為交叉連接月弛;

超大型數(shù)據(jù)盡可能盡力不要寫子查詢,使用連接(JOIN)去替換它:

當(dāng)然科盛,關(guān)于這句話帽衙,也不一定就全是這樣。

1)因?yàn)樵诖笮偷臄?shù)據(jù)處理中贞绵,子查詢是非常常見的厉萝,特別是在查詢出來的數(shù)據(jù)需要進(jìn)一步處理的情況,無論是可讀性還是效率上榨崩,這時(shí)候的子查都是更優(yōu)谴垫。

2)然而在一些特定的場景,可以直接從數(shù)據(jù)庫讀取就可以的母蛛,比如一個(gè)表(A表 a翩剪,b,c字段彩郊,需要內(nèi)部數(shù)據(jù)交集)join自己的效率必然比放一個(gè)子查在where中快得多前弯。

使用聯(lián)合(UNION)來代替手動(dòng)創(chuàng)建的臨時(shí)表

UNION是會把結(jié)果排序的r阶骸!恕出!

union查詢:它可以把需要使用臨時(shí)表的兩條或更多的select查詢合并的一個(gè)查詢中(即把兩次或多次查詢結(jié)果合并起來询枚。)。在客戶端的查詢會話結(jié)束的時(shí)候剃根,臨時(shí)表會被自動(dòng)刪除哩盲,從而保證數(shù)據(jù)庫整齊前方、高效狈醉。使用union來創(chuàng)建查詢的時(shí)候,我們只需要用UNION作為關(guān)鍵字把多個(gè)select語句連接起來就可以了惠险,要注意的是所有select語句中的字段數(shù)目要想同苗傅。

要求:兩次查詢的列數(shù)必須一致(列的類型可以不一樣,但推薦查詢的每一列班巩,相對應(yīng)的類型要一樣)

可以來自多張表的數(shù)據(jù):多次sql語句取出的列名可以不一致渣慕,此時(shí)以第一個(gè)sql語句的列名為準(zhǔn)。

如果不同的語句中取出的行抱慌,有完全相同(這里表示的是每個(gè)列的值都相同)逊桦,那么union會將相同的行合并,最終只保留一行抑进。也可以這樣理解强经,union會去掉重復(fù)的行。

如果不想去掉重復(fù)的行寺渗,可以使用union all匿情。

如果子句中有order by,limit,需用括號()包起來信殊。推薦放到所有子句之后炬称,即對最終合并的結(jié)果來排序或篩選。

注意:

1涡拘、UNION 結(jié)果集中的列名總是等于第一個(gè) SELECT 語句中的列名

2玲躯、UNION 內(nèi)部的 SELECT 語句必須擁有相同數(shù)量的列。列也必須擁有相似的數(shù)據(jù)類型鳄乏。同時(shí)跷车,每條 SELECT 語句中的列的順序必須相同

UNION ALL的作用和語法:

默認(rèn)地,UNION 操作符選取不同的值汞窗。如果允許重復(fù)的值姓赤,請使用 UNION ALL。當(dāng) ALL 隨 UNION 一起使用時(shí)(即 UNION ALL)仲吏,不消除重復(fù)行不铆。

總結(jié)

(1)對于要求全面的結(jié)果時(shí)蝌焚,我們需要使用連接操作(LEFT JOIN / RIGHT JOIN / FULL JOIN);

(2)應(yīng)盡量避免在 where 子句中對字段進(jìn)行 null 值判斷誓斥,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描只洒,如:

備注、描述劳坑、評論之類的可以設(shè)置為 NULL毕谴,其他最好不要使用NULL。

不要以為 NULL 不需要空間距芬,比如:char(100) 型涝开,在字段建立時(shí),空間就固定了框仔, 不管是否插入值(NULL也包含在內(nèi))舀武,都是占用 100個(gè)字符的空間的,如果是varchar這樣的變長字段离斩, null 不占用空間银舱。

可以在num上設(shè)置默認(rèn)值0,確保表中num列沒有null值跛梗,然后這樣查詢:

select id from t where num = 0

(3)in 和 not in 也要慎用寻馏,否則會導(dǎo)致全表掃描,如:

對于連續(xù)的數(shù)值核偿,能用 between 就不要用 in 了:

很多時(shí)候用 exists 代替 in 是一個(gè)好的選擇:

(4)盡量使用數(shù)字型字段诚欠,若只含數(shù)值信息的字段盡量不要設(shè)計(jì)為字符型,這會降低查詢和連接的性能宪祥,并會增加存儲開銷聂薪。這是因?yàn)橐嬖谔幚聿樵兒瓦B 接時(shí)會逐個(gè)比較字符串中每一個(gè)字符,而對于數(shù)字型而言只需要比較一次就夠了蝗羊。

(5)盡量使用表變量來代替臨時(shí)表藏澳。如果表變量包含大量數(shù)據(jù),請注意索引非常有限(只有主鍵索引)耀找。

(6)不要以為使用MySQL的一些連接操作對查詢有多么大的改善翔悠,其實(shí)核心是索引


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市野芒,隨后出現(xiàn)的幾起案子蓄愁,更是在濱河造成了極大的恐慌,老刑警劉巖狞悲,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件撮抓,死亡現(xiàn)場離奇詭異,居然都是意外死亡摇锋,警方通過查閱死者的電腦和手機(jī)丹拯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門站超,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人乖酬,你說我怎么就攤上這事死相。” “怎么了咬像?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵算撮,是天一觀的道長。 經(jīng)常有香客問我县昂,道長肮柜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任七芭,我火速辦了婚禮素挽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘狸驳。我一直安慰自己,他們只是感情好缩赛,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布耙箍。 她就那樣靜靜地躺著,像睡著了一般酥馍。 火紅的嫁衣襯著肌膚如雪辩昆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天旨袒,我揣著相機(jī)與錄音汁针,去河邊找鬼。 笑死砚尽,一個(gè)胖子當(dāng)著我的面吹牛施无,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播必孤,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼猾骡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了敷搪?” 一聲冷哼從身側(cè)響起兴想,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赡勘,沒想到半個(gè)月后嫂便,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡闸与,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年毙替,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了曼振。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,646評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蔚龙,死狀恐怖冰评,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情木羹,我是刑警寧澤甲雅,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站坑填,受9級特大地震影響抛人,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜脐瑰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一妖枚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧苍在,春花似錦绝页、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至初肉,卻和暖如春酷鸦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背牙咏。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工臼隔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人妄壶。 一個(gè)月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓摔握,卻偏偏與公主長得像,于是被迫代替她去往敵國和親盯拱。 傳聞我的和親對象是個(gè)殘疾皇子盒发,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容