sql不為空怎么寫(xiě) 因?yàn)橐粭lSQL,我差

網(wǎng)絡(luò) 分享 時(shí)間: 收藏本文

sql不為空怎么寫(xiě) 因?yàn)橐粭lSQL,我差

sql空字符_sql不為空怎么寫(xiě)_sql為空怎么寫(xiě)

# 反常的 SQL 語(yǔ)句

我瞇開(kāi)朦朧的雙眼,才發(fā)現(xiàn)剛才的發(fā)聲來(lái)源于我的組長(zhǎng)莊哥,看到他在緊張的點(diǎn)開(kāi)日志系統(tǒng)查看日志,我預(yù)感到有什么不妙的事情發(fā)生。

仔細(xì)一問(wèn)才知道,原來(lái)就在我瞇眼的期間,線上數(shù)據(jù)庫(kù)服務(wù)器的 CPU 被打滿,同時(shí)觸發(fā)了生產(chǎn)數(shù)據(jù)庫(kù)只讀延遲的限定時(shí)間并且發(fā)出告警,而且告警的過(guò)程持續(xù)了半個(gè)小時(shí)。

這讓我倒吸了一口涼氣,因?yàn)槲覀兘M做的系統(tǒng)很多都用的是同一個(gè)數(shù)據(jù)庫(kù)服務(wù)器,日用戶活躍量有好幾十萬(wàn),如果服務(wù)器崩潰了將會(huì)使所有的系統(tǒng)服務(wù)都不可用。

于是我們趕緊通過(guò) SQL 日志進(jìn)行問(wèn)題查找,最后排查出來(lái)是因?yàn)橐粡?SQL 的高量查詢(xún)沒(méi)有走索引導(dǎo)致。

日志列表顯示,這條 SQL 語(yǔ)句的掃描行數(shù)達(dá)到了上百萬(wàn),基本就是全表掃描的情況,而且半個(gè)小時(shí)的時(shí)間查詢(xún)了達(dá)上萬(wàn)次,每條 SQL 查詢(xún)的耗時(shí)都在 以上。

我的天啊,難怪服務(wù)器會(huì) CPU 打滿,這么一條耗時(shí)的 SQL 語(yǔ)句查詢(xún)量這么大,數(shù)據(jù)庫(kù)的資源當(dāng)然是直接就崩潰了。

這是當(dāng)時(shí)那條 SQL 的查詢(xún)情況:

sql空字符_sql為空怎么寫(xiě)_sql不為空怎么寫(xiě)

# 臨時(shí)處理

看了這條語(yǔ)句,我又倒吸一口涼氣,這不就是我寫(xiě)的系統(tǒng)調(diào)用的 SQL 語(yǔ)句嗎?完了,這回逃不掉了,真是人在睡夢(mèng)里,鍋從天上來(lái)。

sql空字符_sql不為空怎么寫(xiě)_sql為空怎么寫(xiě)

當(dāng)然,因?yàn)槭俏易约簩?xiě)的 SQL,所以我一看就知道這條語(yǔ)句是有問(wèn)題的。

根據(jù)我的代碼處理,這條 SQL 的調(diào)用還少了個(gè)重要的參數(shù) ,這個(gè)參數(shù)沒(méi)有傳的話是不應(yīng)該走這條 SQL 查詢(xún)的。

在我的設(shè)計(jì)里,該參數(shù)是數(shù)據(jù)表里一個(gè)聯(lián)合索引的最左側(cè)字段,如果該字段沒(méi)有傳值的話,那么索引就不會(huì)生效了。

KEY?`idx_userfruitid_type`?(`user_fruit_id`,`task_type`,`receive_start_time`,`receive_end_time`)?USING?BTREE

雖然定位到了 SQL 語(yǔ)句,但是線上的問(wèn)題刻不容緩,總不可能找出 Bug 改完再上線吧。

所以,我們只能做了一個(gè)臨時(shí)處理,就是在原來(lái)的表上多加了一個(gè)聯(lián)合索引,其實(shí)就是去掉了 字段,讓這些高量的查詢(xún)都能走新的索引。

就像下面這樣:

KEY?`idx_task_type_receive_start_time`?(`task_type`,`receive_start_time`,`receive_end_time`,`created_time`)?USING?BTREE

加上索引后,SQL 的掃描行數(shù)就大幅度的降低了,重啟實(shí)例后就又能正常運(yùn)行了。

# 最左匹配原則

那么為什么最左側(cè)的字段沒(méi)傳索引就不生效了,這是因?yàn)? 的聯(lián)合索引是基于“最左匹配原則”匹配的。

我們都知道,索引的底層是 B+ 樹(shù)結(jié)構(gòu),聯(lián)合索引的結(jié)構(gòu)也是 B+ 樹(shù),只不過(guò)鍵值數(shù)量不是一個(gè),而是多個(gè),構(gòu)建一顆 B+ 樹(shù)只能根據(jù)一個(gè)值來(lái)構(gòu)建,因此數(shù)據(jù)庫(kù)依據(jù)聯(lián)合索引最左的字段來(lái)構(gòu)建 B+ 樹(shù)。

例如我們用兩個(gè)字段(name,age)這個(gè)聯(lián)合索引來(lái)分析:

sql空字符_sql不為空怎么寫(xiě)_sql為空怎么寫(xiě)

圖片來(lái)源于林曉斌老師的《 實(shí)戰(zhàn) 45 講》課程

當(dāng)我們?cè)? 條件中查找 name 為“張三”的所有記錄的時(shí)候,可以快速定位到 ID4,并且查出所有包含“張三”的記錄。

而如果要查找“張三,10”這一條特定的數(shù)據(jù),就可以用 name = "張三" and age = 10獲取。

因?yàn)槁?lián)合索引的鍵值對(duì)是兩個(gè),所以只要前面的 name 確定的情況下就可以進(jìn)一步定位到具體的 age 記錄。

但是如果你的查詢(xún)條件只有 age 的話,那么索引就不會(huì)生效,因?yàn)闆](méi)有匹配最左邊的字段,后面所有的索引字段都不會(huì)生效。

# 找出 Bug

雖然臨時(shí)做了處理,但問(wèn)題并不算解決,很明顯是系統(tǒng)出現(xiàn)了 Bug 才會(huì)有走這樣的查詢(xún)條件。

因?yàn)槭俏易约簩?xiě)的代碼,所以知道是哪條 SQL 后我就馬上定位到了代碼里的具體方法,后來(lái)才發(fā)現(xiàn)是因?yàn)槲覍?duì) 字段的判空處理不生效所致。

因?yàn)樵撟侄问菑恼{(diào)用方傳過(guò)來(lái)的,所以我在方法參數(shù)里對(duì)該字段做了非空限制的注解,也就是 包下的 @:

public class GardenUserTaskListReq implements Serializable {
private static final long serialVersionUID = -9161295541482297498L;
@ApiModelProperty(notes = "水果id") @NotNull(message = "水果id不能為空") private Long userFruitId; /**以下省略*/ .....................}

雖然加上該注解來(lái)做非空校驗(yàn),但我卻沒(méi)有在參數(shù)加上另一個(gè)注解 @。

該注解如果沒(méi)加上的話,那么調(diào)用 包下的校驗(yàn)規(guī)則就都不生效,正確的寫(xiě)法是在 層方法的參數(shù)前面加上注解:

sql為空怎么寫(xiě)_sql空字符_sql不為空怎么寫(xiě)

除此之外,因?yàn)? 這個(gè)字段是另一張表的主鍵,我在代碼里也沒(méi)有對(duì)這張表是否存在這個(gè) id 做查詢(xún)判斷。

這樣一來(lái),無(wú)論調(diào)用方傳什么值過(guò)來(lái)都會(huì)直接觸發(fā) SQL 查詢(xún),并且在不跑索引的情況下直接走全表掃描。

sql空字符_sql不為空怎么寫(xiě)_sql為空怎么寫(xiě)

不得不說(shuō),這真是個(gè)低級(jí)錯(cuò)誤,說(shuō)真的,我對(duì)這個(gè)原因真是感到嘀笑皆非,再怎么說(shuō)也工作幾年了,怎么還犯一些新手級(jí)別的錯(cuò)誤呢,這臉打得真是讓我相當(dāng)慚愧。

# 總結(jié)

雖然是低級(jí)錯(cuò)誤,但造成的后果也算挺嚴(yán)重了,這次事件也讓我更加的警醒,在以后的開(kāi)發(fā)工作中必須要遵守該有的原則,大概有這么幾點(diǎn):

千里之堤毀于蟻穴,有時(shí)一個(gè)小 Bug 很容易就引發(fā)整個(gè)系統(tǒng)的崩盤(pán),這一次的問(wèn)題也讓我更加深刻的認(rèn)識(shí)到了 代碼的重要性,不管業(yè)務(wù)開(kāi)發(fā)的工作量有多麻煩,這一步操作絕對(duì)不能忽視。

相關(guān)專(zhuān)題 索引sql數(shù)據(jù)庫(kù)
信息流廣告 周易 易經(jīng) 代理招生 二手車(chē) 網(wǎng)絡(luò)營(yíng)銷(xiāo) 旅游攻略 非物質(zhì)文化遺產(chǎn) 查字典 社區(qū)團(tuán)購(gòu) 精雕圖 戲曲下載 抖音代運(yùn)營(yíng) 易學(xué)網(wǎng) 互聯(lián)網(wǎng)資訊 成語(yǔ) 成語(yǔ)故事 詩(shī)詞 工商注冊(cè) 注冊(cè)公司 抖音帶貨 云南旅游網(wǎng) 網(wǎng)絡(luò)游戲 代理記賬 短視頻運(yùn)營(yíng) 在線題庫(kù) 國(guó)學(xué)網(wǎng) 知識(shí)產(chǎn)權(quán) 抖音運(yùn)營(yíng) 雕龍客 雕塑 奇石 散文 自學(xué)教程 常用文書(shū) 河北生活網(wǎng) 好書(shū)推薦 游戲攻略 心理測(cè)試 石家莊人才網(wǎng) 考研真題 漢語(yǔ)知識(shí) 心理咨詢(xún) 手游安卓版下載 興趣愛(ài)好 網(wǎng)絡(luò)知識(shí) 十大品牌排行榜 商標(biāo)交易 單機(jī)游戲下載 短視頻代運(yùn)營(yíng) 寶寶起名 范文網(wǎng) 電商設(shè)計(jì) 免費(fèi)發(fā)布信息 服裝服飾 律師咨詢(xún) 搜救犬 Chat GPT中文版 經(jīng)典范文 優(yōu)質(zhì)范文 工作總結(jié) 二手車(chē)估價(jià) 實(shí)用范文 古詩(shī)詞 衡水人才網(wǎng) 石家莊點(diǎn)痣 養(yǎng)花 名酒回收 石家莊代理記賬 女士發(fā)型 搜搜作文 石家莊人才網(wǎng) 鋼琴入門(mén)指法教程 詞典 圍棋 chatGPT 讀后感 玄機(jī)派 企業(yè)服務(wù) 法律咨詢(xún) chatGPT國(guó)內(nèi)版 chatGPT官網(wǎng) 勵(lì)志名言 河北代理記賬公司 文玩 語(yǔ)料庫(kù) 游戲推薦 男士發(fā)型 高考作文 PS修圖 兒童文學(xué) 買(mǎi)車(chē)咨詢(xún) 工作計(jì)劃 禮品廠 舟舟培訓(xùn) IT教程 手機(jī)游戲推薦排行榜 暖通,電地暖, 女性健康 苗木供應(yīng) ps素材庫(kù) 短視頻培訓(xùn) 優(yōu)秀個(gè)人博客 包裝網(wǎng) 創(chuàng)業(yè)賺錢(qián) 養(yǎng)生 民間借貸律師 綠色軟件 安卓手機(jī)游戲 手機(jī)軟件下載 手機(jī)游戲下載 單機(jī)游戲大全 免費(fèi)軟件下載 石家莊論壇 網(wǎng)賺 手游下載 游戲盒子 職業(yè)培訓(xùn) 資格考試 成語(yǔ)大全 英語(yǔ)培訓(xùn) 藝術(shù)培訓(xùn) 少兒培訓(xùn) 苗木網(wǎng) 雕塑網(wǎng) 好玩的手機(jī)游戲推薦 漢語(yǔ)詞典 中國(guó)機(jī)械網(wǎng) 美文欣賞 紅樓夢(mèng) 道德經(jīng) 標(biāo)準(zhǔn)件 電地暖 網(wǎng)站轉(zhuǎn)讓 鮮花 書(shū)包網(wǎng) 英語(yǔ)培訓(xùn)機(jī)構(gòu) 電商運(yùn)營(yíng)