64MySQL-分頁(yè)查詢(xún)&表連接&count統(tǒng)計(jì)&索引優(yōu)化總結(jié)

1 Mysql 分頁(yè)查詢(xún)sql 執(zhí)行原理疆液?

2,千萬(wàn)級(jí)數(shù)據(jù)mysql 分頁(yè)查詢(xún)?nèi)绾蝺?yōu)化

3陕贮,Mysql表連接底層實(shí)現(xiàn)原理
·

4堕油,nested_Loop Join(NLJ)與Block Nested-Loop(BNL)連表算法的區(qū)別

5,in/exist/count(*)count(1) count(列名)查詢(xún)優(yōu)化

6肮之,EXPLAIN 分析sql語(yǔ)句 type 最低滿(mǎn)足什么級(jí)別

7掉缺,為什么阿里巴巴官方手冊(cè)不推薦使用存儲(chǔ)過(guò)程。

8戈擒,阿里官方手冊(cè)mysql 索引優(yōu)化總結(jié)》

分頁(yè)查詢(xún)優(yōu)化:

select * from employees limit 10000,10;
select * from employees limit 100000,10;
select * from employees limit 1000000,10;
select * from employees limit 3000000,10;

select * from employees limit 3000000,10;

image.png

從表中只查詢(xún)10條數(shù)據(jù)眶明,實(shí)際上底層讀取了300000條數(shù)據(jù),然后讀取最后10條
這種分頁(yè)查詢(xún)采用全表掃描的方式筐高,查詢(xún)效率極低搜囱。
1,根據(jù)主鍵且連續(xù)的主鍵排序的分頁(yè)查詢(xún):

EXPLAIN select * from employees where id>3000003 limit 10;

原理: 根據(jù)主鍵索引id排除< 3000003 柑土,取后10條數(shù)據(jù)避免全表掃描
缺點(diǎn): 如果主鍵id不連續(xù) 蜀肘,可能無(wú)法實(shí)現(xiàn)效果。
2稽屏,非主鍵索引方式分頁(yè)優(yōu)化:

select * from employees order by id limit 100000,10;

SELECT * from employees  e  inner join (

select id from employees a order by a.id limit 100000,10 ) ed on e.id=ed.id

使用復(fù)合索引嵌套子查詢(xún)扮宠,效率可以提高一半。

阿里巴巴手冊(cè):

image.png

數(shù)據(jù)量超過(guò)500萬(wàn)或者大于2g的時(shí)候建議分表

count(*) 優(yōu)化:

臨時(shí)關(guān)閉mysql 的查詢(xún)緩存狐榔,為了查看sql多次執(zhí)行的真實(shí)時(shí)間坛增。

set global query_cache_size=0;
set global query_cache_type=0;
1,count(field) 不包含字段值為null 的值获雕;
2,count() 包含字段為null 的值收捣;
3届案,select(
) 與select(1) 在InnnDB 中性能沒(méi)有任何區(qū)別,處理方式相同罢艾。

5.6版本:
1, select count(1) from employees; 使用輔助聯(lián)合索引計(jì)數(shù)
2楣颠, select count(id) from employees; 使用輔助索引計(jì)數(shù)
3, select count(name) from employees; 使用輔助索引計(jì)數(shù)
4昆婿, select count() from employees; 使用輔助索引計(jì)數(shù)
5球碉, select count(id) from employees force index (PRIMARY) 使用主鍵索引;
從效率上看: count(1) ==count(
)>count(name)>count(id)
因?yàn)橹麈I索引的id 對(duì)應(yīng)的葉子節(jié)點(diǎn)中存放data 數(shù)據(jù)仓蛆,加載內(nèi)存中計(jì)數(shù)的時(shí)候比較慢睁冬。 推薦使用 count(*);

在mysql 5.7 count(*) 會(huì)選擇聚集索引看疙,進(jìn)行一次內(nèi)部handler函數(shù)調(diào)用豆拨,即可快速獲得該表總數(shù),執(zhí)行計(jì)劃Extra 顯示 select tables optimized away SELECT 操作已經(jīng)優(yōu)化到不能再優(yōu)化
如果聚集索引比較大(或者說(shuō)表數(shù)據(jù)量比較大)能庆。沒(méi)有完全加載到buffer pool 中的話(huà),MYSQL5.7的查詢(xún)方式有可能反而更慢施禾, 還不如原先放方式 MYSQL5.6

EXPLAIN select count(1) from employees;
EXPLAIN select count(id) from employees;
EXPLAIN select count(name) from employees;
EXPLAIN select count(*) from employees;
EXPLAIN select count(id) from employees force index(PRIMARY) 強(qiáng)制使用聚集索引

聚集索引和非聚集索引的區(qū)別:
聚集索引: 就是主鍵id 非聚集索引就是自定義的userName 字段
其中聚集索引 clustered index(id) , 非聚集索引index (UserName)

InnoDB 表中在沒(méi)有默認(rèn)主鍵的情況下會(huì)生成一個(gè)6 byte 空間的自增長(zhǎng)主鍵,可以用
select _rowid from table 查詢(xún)的是對(duì)應(yīng)的主鍵值 select _rowid from employees

常見(jiàn)的優(yōu)化方案:
1搁胆,對(duì)于 myisam 存儲(chǔ)引擎的表做不帶where 條件的count 查詢(xún)性能是很高的弥搞,因?yàn)閙ysiam 存儲(chǔ)的表總行會(huì)被mysql 存儲(chǔ)在磁盤(pán)上,查詢(xún)不需要操作
2 show table status
3, 使用Redis set key 記錄表總數(shù)渠旁。

Join 關(guān)聯(lián)表查詢(xún)


EXPLAIN select * from mayikt_1 left join mayikt_2 on mayikt_1.t1= mayikt_2.t1;
EXPLAIN select * from mayikt_2 left join mayikt_1 on mayikt_1.t1= mayikt_2.t1;
EXPLAIN select * from mayikt_2 right join mayikt_1 on mayikt_1.t1= mayikt_2.t1;

Nested-Loop Join(NLJ) 嵌套循環(huán)連接 算法
Block Nested-Loop Join (BNL) 基于塊的嵌套循環(huán)連接 算法

Nested-Loop Join 嵌套循環(huán)連接 算法(主鍵關(guān)聯(lián)查詢(xún))
EXPLAIN select * from mayikt_1 inner join mayikt_2 on mayikt_1.t1= mayikt_2.t1;

image.png

全表掃描查詢(xún)到mayikt_2 表中索引的數(shù)據(jù)攀例,在根據(jù) mayikt2 中的t1 索引字段數(shù)據(jù)查詢(xún)mayikt1 索引字段中的數(shù)據(jù),總共掃描2000行
驅(qū)動(dòng)表 mayikt2(小表)被驅(qū)動(dòng)表: mayikt_1(大表)
優(yōu)化器一般會(huì)選擇小表做驅(qū)動(dòng)表顾腊,所以使用 inner join 時(shí) 粤铭,排在后面的表并不一定

Block Nested-Loop Join 基于塊的嵌套循環(huán)連接 算法(非索引關(guān)聯(lián)查詢(xún))
關(guān)聯(lián)查詢(xún)使用的是 BNL 算法:
EXPLAIN select * from mayikt_2 straight_join mayikt_1 on mayikt_1.t2= mayikt_2.t2;

image.png

原理:
1.將mayikt2表中所有的數(shù)據(jù)放入到j(luò)oin_buffer 中
2.在讀取mayikt1表中每行數(shù)據(jù)與join_buffer中數(shù)據(jù)實(shí)現(xiàn)匹配關(guān)聯(lián)
3.最后在返回查詢(xún)的數(shù)據(jù)
1000*32869次 查詢(xún)效率極低。

有索引是情況下 NLJ 算法比BNL 算法性能要高杂靶;
對(duì)于關(guān)聯(lián)sql的優(yōu)化:
1梆惯, 超過(guò)三個(gè)表禁止join, 需要join 的字段 ,數(shù)據(jù)類(lèi)型必須一致吗垮,多表關(guān)聯(lián)查詢(xún)時(shí)垛吗,保證被關(guān)聯(lián)的字段需要有索引,盡量使用NLJ 算法抱既;
2职烧, 小表驅(qū)動(dòng)大表 ,寫(xiě)多表連接sql 時(shí)如果明確知道那張表是小表可以用 straight_join 寫(xiě)法固定方式 防泵,省去mysql 優(yōu)化器自己判斷時(shí)間蚀之。

EXPLAIN select * from mayikt_2 straight_join mayikt_1 on mayikt_1.t2= mayikt_2.t2;

in 和exist 優(yōu)化:
也是需要遵循原則;
原則: 小表驅(qū)動(dòng)大表捷泞,即小的數(shù)據(jù)集驅(qū)動(dòng)大的數(shù)據(jù)集

如果 mayikt_b 中的數(shù)據(jù)小于mayikt_a 的數(shù)據(jù)可以使用in

select * from mayikt_a where id in (select id from mayikt_b)

底層類(lèi)似于這樣實(shí)現(xiàn)
for(select id from mayikt_B){
     select * from mayikt_a where mayikt_a.id = mayikt_b.id
 }
如果mayikt_a中的數(shù)據(jù)小于mayikt_b數(shù)據(jù)可以使用exists 
select * from mayikt_a where exists (select id from mayikt_b where mayikt_b.id = mayikt_a.id)
 for(select * from mayikt_a){
      select * from mayikt_a where mayikt_b.id = mayikt_a.id
 }

1 mysql 索引優(yōu)化原則:
2 核心點(diǎn): B+樹(shù)足删,優(yōu)化原則: 常見(jiàn)方式,分頁(yè)锁右,排序失受,連表, count(*)
3 MYSQL 索引底層采用B+樹(shù)咏瑟; 減少磁盤(pán)IO操作拂到,支持高效的范圍查詢(xún):

4 優(yōu)化原則:
核心: 先定位慢查詢(xún),在通過(guò)慢查詢(xún)?nèi)罩疚募? 分析sql 語(yǔ)句码泞;
分析sql 語(yǔ)句工具: ExPLAIN/trace 工具
EXPLAIN type 滿(mǎn)足級(jí)別: type最低 滿(mǎn)足 range 范圍查詢(xún)級(jí)別
防止索引失效兄旬,避免全表掃描;

5余寥, 優(yōu)化方案:
常見(jiàn)方案:
常見(jiàn)方式领铐,分頁(yè),排序宋舷,連表绪撵,count(*)
1,必須遵循最佳左前綴原則 防止索引失效
2祝蝠,盡量使用覆蓋索引 查詢(xún)列都是加上索引 音诈,減少select *
3,is null 绎狭,is not null 索引會(huì)失效细溅,空值用專(zhuān)門(mén)特定的常量值定義; dfe
4坟岔, like 模糊查詢(xún)遵循最佳左前綴原則 谒兄,使用復(fù)合索引模糊查詢(xún)
5,排序相關(guān): 最佳左前綴原則社付,避免 filesort

6, 分頁(yè)查詢(xún) 承疲, 根據(jù) where id 條件過(guò)濾 offset 或者使用子查詢(xún)先定位id, 在查詢(xún)效率可以提高一半鸥咖,但是如果數(shù)據(jù)量大于500萬(wàn)的情況下建議使用分表燕鸽。
7,連表查詢(xún) : 小表驅(qū)動(dòng)大表數(shù)據(jù)避免全表掃描啼辣,超過(guò)三張表禁止使用join

8啊研,count(*) 查詢(xún)優(yōu)化 ,輔助索引count 比主鍵索引count
效率高; mysql5.7 主鍵id count mysql5.6 輔助索引 count

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末党远,一起剝皮案震驚了整個(gè)濱河市削解,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌沟娱,老刑警劉巖氛驮,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異济似,居然都是意外死亡矫废,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)砰蠢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蓖扑,“玉大人,你說(shuō)我怎么就攤上這事台舱÷筛埽” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵柿赊,是天一觀(guān)的道長(zhǎng)俩功。 經(jīng)常有香客問(wèn)我,道長(zhǎng)碰声,這世上最難降的妖魔是什么诡蜓? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮胰挑,結(jié)果婚禮上蔓罚,老公的妹妹穿的比我還像新娘。我一直安慰自己瞻颂,他們只是感情好豺谈,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著贡这,像睡著了一般茬末。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上盖矫,一...
    開(kāi)封第一講書(shū)人閱讀 51,245評(píng)論 1 299
  • 那天丽惭,我揣著相機(jī)與錄音,去河邊找鬼辈双。 笑死责掏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的湃望。 我是一名探鬼主播换衬,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼痰驱,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了瞳浦?” 一聲冷哼從身側(cè)響起担映,我...
    開(kāi)封第一講書(shū)人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎术幔,沒(méi)想到半個(gè)月后另萤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體湃密,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡诅挑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了泛源。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拔妥。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖达箍,靈堂內(nèi)的尸體忽然破棺而出没龙,到底是詐尸還是另有隱情,我是刑警寧澤缎玫,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布硬纤,位于F島的核電站,受9級(jí)特大地震影響赃磨,放射性物質(zhì)發(fā)生泄漏筝家。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一邻辉、第九天 我趴在偏房一處隱蔽的房頂上張望溪王。 院中可真熱鬧,春花似錦值骇、人聲如沸莹菱。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)道伟。三九已至,卻和暖如春使碾,著一層夾襖步出監(jiān)牢的瞬間蜜徽,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工部逮, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留娜汁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓兄朋,卻偏偏與公主長(zhǎng)得像掐禁,于是被迫代替她去往敵國(guó)和親怜械。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354