聊聊最近的技術(shù)之路
大家好,我是Leo。
2月22號(hào)又是被群友催更的一天,今天28號(hào)了。已經(jīng) 11-12天沒更了。今晚決定熬夜更一篇。順便聊一下我最近忙的事情。

最近做了啥
Andon項(xiàng)目 重構(gòu)電商微服務(wù)系統(tǒng) 重構(gòu)電商底層的數(shù)據(jù)結(jié)構(gòu) 手?jǐn)]微服務(wù)從0-1,不過最后因?yàn)楹芏嗟胤綄懖缓?,暫時(shí)放棄了 白天的話肯定是工作嘛,我是認(rèn)真工作的小青年 理財(cái)
Andon的話讓我重溫了一下C#。

電商微服務(wù)的話只能給你們看這個(gè)圖了,直接吃我98的內(nèi)存,我開發(fā)的時(shí)候申請(qǐng)IO都搞不了

重構(gòu)底層數(shù)據(jù)結(jié)構(gòu)的話主要就是數(shù)據(jù)字段性能優(yōu)化技巧了,這篇文章下面也是主要介紹的這個(gè)。

手?jǐn)]微服務(wù)的話就看這張圖吧

工作的話,不方便發(fā),我怕再碰點(diǎn)什么商業(yè)機(jī)密,說不清,之前英諾激光就那么惡心人。
理財(cái)?shù)脑捝蠄D吧

聊正事吧
這篇主要聊一下我在做優(yōu)化數(shù)據(jù)結(jié)構(gòu)的一些想法。
優(yōu)化的第一點(diǎn)
也是最要命的就是數(shù)據(jù)字段的設(shè)計(jì)問題,我這里主要考慮四點(diǎn)
冷熱分離 應(yīng)用中主從表可以出現(xiàn)重復(fù)字段為了減少回表 常用字段全部加上索引,以及考慮聯(lián)合索引,索引失效,最左匹配原則,索引下推問題 MySQL的緩存機(jī)制問題。
從這四點(diǎn)出發(fā)。冷熱分離的話我們舉一個(gè)商品表的例子,我把修改量比較大的單獨(dú)放一張表,改動(dòng)量不大的給他放在了主表,同時(shí)考慮到查詢一個(gè)商品的時(shí)候往往會(huì)帶上?名稱+分類?我給他加了聯(lián)合索引,這樣就可以減少回表了。
冷熱分離的話還涉及到另外一點(diǎn)就是MySQL的緩存機(jī)制,當(dāng)一個(gè)表沒出現(xiàn)修改的時(shí)候,下一次查詢,不會(huì)產(chǎn)生磁盤IO的開銷了,MySQL會(huì)直接讀緩存中的數(shù)值然后返給客戶端。


索引失效的話,主要考慮的是數(shù)據(jù)類型不一致導(dǎo)致失效,常見的就是下面四種。一定要留意你們的狀態(tài)是int類型還是varchar類型。
出售狀態(tài) 熱賣狀態(tài) 特價(jià)狀態(tài) 訂單號(hào)


這里如果還想優(yōu)化細(xì)一些的話,可以考慮把固定的字段改成char類型,不需要使用varchar。
順著在聊一下char和varchar的區(qū)別
char是固定的類型,varchar是可變的類型, 插入char字段時(shí),多余當(dāng)前字段的大小的自動(dòng)舍去,varchar相反,他會(huì)可以變動(dòng) char查找效率會(huì)很高,varchar查找效率會(huì)更低 char和varchar類型的字段在計(jì)算索引長度時(shí),char會(huì)+1,varchar會(huì)+2
其實(shí)就是空間換時(shí)間的一個(gè)說法,到底是性能最重要還是存儲(chǔ)空間最重要了。
優(yōu)化第二點(diǎn)
主要考慮一些主從表的問題
如果是一對(duì)一,可以采用 inner join 如果是一對(duì)多,可以采用 left join
一對(duì)一的話?這個(gè)地方我今天踩了一個(gè)坑,我一直以為多表操作left join搞定,偶爾間發(fā)現(xiàn)了不一樣的操作不一樣的說法,下面我們介紹一下


很清晰的看出一樣的語句,不同的關(guān)聯(lián)方式查出來不同的結(jié)果。這里不同點(diǎn)主要有兩塊?possible_keys?和?Extra。possible_keys沒啥好說的,主要說一下?Extra?。
Using where:表示優(yōu)化器需要通過索引回表查詢數(shù)據(jù) Using index:表示直接訪問索引就足夠獲取到所需要的數(shù)據(jù),不需要通過索引回表 Using index condition:在5.6版本后加入的新特性(Index Condition Pushdown)會(huì)先條件過濾索引,過濾完索引后找到所有符合索引條件的數(shù)據(jù)行,隨后用 WHERE 子句中的其他條件去過濾這些數(shù)據(jù)行;
我對(duì) Using index condition 的理解是:首先 mysql 服務(wù)端(server) 和 存儲(chǔ)引擎(storage engine) 是兩個(gè)組件, server 負(fù)責(zé) sql的parse執(zhí)行; storage engine 去真正的 做 數(shù)據(jù)/index的 讀取/寫入. 以前是這樣: server 命令 storage engine 按 index 把相應(yīng)的 數(shù)據(jù) 從 數(shù)據(jù)表讀出, 傳給server, server來按 where條件 做選擇; 現(xiàn)在 ICP則是在 可能的情況下, 讓storage engine 根據(jù)index 做判斷, 如果不符合 條件 則無須 讀 數(shù)據(jù)表. 這樣 節(jié)省了disk IO.。
這里闡述一下這兩種SQL,因?yàn)殛P(guān)聯(lián)查詢輸出那里我都用了全部列,為了讀者方便觀察。我們可以清晰的看到結(jié)果1?的性能查詢優(yōu)于?結(jié)果2?。所以一對(duì)一查詢時(shí)可以優(yōu)先考慮?inner join
一對(duì)多的話?肯定還是優(yōu)先考慮?left join的,但是我用的比較多的是主從表查詢完之后,列表需要做一次order by create_time 排序


很清晰的發(fā)現(xiàn)做了一次order by之后,索引就失效了,這里出現(xiàn)了上文的?Using index condition?的原因是我們公司的前輩給?create_time?也加了索引。如果不加索引的話就會(huì)失效,加了索引的話部分生效。具體怎么解決后面會(huì)繼續(xù)聊的,這里先透露一下 可以根據(jù)?key_len?解決。key_len又是有該字段的類型長度和null值決定的。
name3?varchar(20) NOT NULL DEFAULT
name1?char(20) DEFAULT NULL,
上面是2個(gè)字段的定義,1個(gè)允許NULL,一個(gè)NOT NULL,一個(gè)char,一個(gè)varchar
所以key_len=(20*3 + 1)+(20 * 3 + 2)= 123相信有人會(huì)問了,+1是干嘛,+2是干嘛。這就告訴大家,+1是因?yàn)镸ySQL需要1個(gè)字節(jié)標(biāo)識(shí)NULL,+2是因?yàn)閚ame3字段為varchar,是變長字段需要+2。
非常歡迎大家加我個(gè)人微信有關(guān)后端方面的問題我們?cè)谌簝?nèi)一起討論!?我們下期再見!
長按上方掃碼二維碼,加我微信,拉你進(jìn)群

