本書首先介紹SQL整體優(yōu)化、快速優(yōu)化實(shí)施、如何讀懂執(zhí)行計(jì)劃、如何左右執(zhí)行計(jì)劃這四大必殺招。傳授一個(gè)先整體后局部的宏觀解決思路,走進(jìn)“道”的世界。接下來帶領(lǐng)讀者飛翔在“術(shù)”天空。教授體系結(jié)構(gòu)、邏輯結(jié)構(gòu)、表設(shè)計(jì)、索引設(shè)計(jì)、表連接這五大要領(lǐng),如何解決問題,準(zhǔn)確地說,是如何不改寫即完成SQL優(yōu)化。隨后本書指引大家學(xué)會(huì)等價(jià)改寫、過程包優(yōu)化、高級(jí)SQL、分析函數(shù)、需求優(yōu)化這些相關(guān)的五大神功。這還是“術(shù)”的范疇,依然是關(guān)于如何解決問題,只不過這次是如何改寫SQL完成優(yōu)化。本書對(duì)數(shù)據(jù)庫開發(fā)人員、DBA都將帶來或多或少的幫助
方法意識(shí)巧妙融入,腦圖表格清晰展現(xiàn);
海量案例完美結(jié)合,線上線下拓展延伸。
序
這是自上一本《收獲,不止Oracle》一書后,我第二次為作者寫序,我知道這又是一本極不尋常的書。
果然,初翻開此書,就給我?guī)砹梭@喜。作者將全書脈絡(luò)展現(xiàn)得非常清晰,先在前言中通過小故事梳理出SQL優(yōu)化的方法論,接下來將各SQL優(yōu)化的知識(shí)點(diǎn)融入到方法論中,形成了全書目錄,從而讓讀者明白為什么要講解這些知識(shí),學(xué)了這些知識(shí)對(duì)優(yōu)化有什么幫助。更讓人稱道的是,這個(gè)目錄是以一個(gè)生動(dòng)有趣的足跡圖展現(xiàn)在讀者面前的,不落俗套的同時(shí)給人一種視覺上的驚艷感。這是誰的足跡,分明是你自己的足跡!于是,一種強(qiáng)烈的代入感油然而生,來,邁開雙腿,學(xué)習(xí)著,思考著,奔跑著!
足跡所到之處,感動(dòng)如影隨形,只因案例無數(shù)。我看到了作者十多年如一日在工作的荊棘之路中勇往直前的精神,看到了作者在攻堅(jiān)克難后的沉思總結(jié),看到了作者作為感動(dòng)福富十大人物的一種堅(jiān)持的精神!更難得的是,這些實(shí)戰(zhàn)案例背后密布的代碼不但沒讓我迷糊,反倒讓我覺得非常親切,因?yàn)楸緯鵀槊總(gè)章節(jié)的案例都進(jìn)行了詳細(xì)的分類和匯總,讓人一目了然。
翻開此書,作者極佳的文字表現(xiàn)能力和技術(shù)實(shí)力立刻躍然紙上,讀者一定會(huì)感嘆作者怎么具備將晦澀難懂的技術(shù)書寫得如此清新脫俗的能力!不過我卻一點(diǎn)都不感到意外,始終是抱著一種驗(yàn)證的心態(tài)來閱讀,其中的原因來自于他在公司的雙重身份。梁敬彬是福富特級(jí)專家,又是公司四星級(jí)內(nèi)訓(xùn)師,前者的榮譽(yù)顯示了IT人的輝煌技術(shù)成就,后者的勛章證明了老師的杰出教學(xué)能力,兩者一完美結(jié)合,書中再多的驚喜也不會(huì)使你感到意外了。我看到IT企業(yè)中有很多技術(shù)牛人由于在表達(dá)溝通交流方面的欠缺,在傳幫帶方面做得不夠好;也看到很多技術(shù)人員具備良好的溝通能力卻苦于技術(shù)不過硬而無法與人深入交流。作者在這方面給我們廣大IT技術(shù)人員樹立了一個(gè)很好的榜樣,會(huì)打硬仗還要會(huì)帶兵。據(jù)統(tǒng)計(jì)每年接受梁敬彬培訓(xùn)的福富技術(shù)人員多達(dá)400人,加上他每年在公司以外的演講和技術(shù)分享,梁老師可謂桃李滿天下,給梁老師點(diǎn)個(gè)大大的贊!
隨著對(duì)此書的進(jìn)一步了解,我知道作者邀請(qǐng)了業(yè)界許多專家對(duì)此書進(jìn)行完善、美化、審核。至此,我又讀出了一種精神,叫“團(tuán)隊(duì)精神”,此書正是團(tuán)隊(duì)協(xié)作的結(jié)晶!作者把工作中的團(tuán)隊(duì)精神帶入書籍編寫中,值得稱道。我在感嘆此書的不同凡響之余,更感慨團(tuán)隊(duì)的無窮力量!
此書必將成為IT書籍的又一個(gè)經(jīng)典傳奇,我相信廣大讀者在翻閱此書時(shí),除了可以學(xué)到精妙的SQL優(yōu)化實(shí)用技術(shù)外,還可以從無數(shù)案例中感受到什么叫激情、震撼;從方法論總結(jié)上理解什么叫升華、用心;從各種梳理的表格和思維導(dǎo)圖中體會(huì)什么叫清晰、極致;從書的精妙視覺設(shè)計(jì)中領(lǐng)悟什么叫求道、協(xié)作。我想說的是,從菜鳥到SQL大師其實(shí)不易,真正的大師不止是技術(shù)上精湛,還需要一種精神。這種精神,還請(qǐng)你在閱讀本書中感悟吧!
福富軟件公司副董事長 楊林
匠心獨(dú)運(yùn) 獨(dú)樹一幟
——與梁敬彬先生序
在拿到敬彬新書的稿件時(shí),我的腦海第一時(shí)間呈現(xiàn)出來的就是這八個(gè)字:匠心獨(dú)運(yùn),獨(dú)樹一幟。
技術(shù)書籍的寫作也是一個(gè)創(chuàng)作過程,平庸者千篇一律,卓越者自出機(jī)抒。
寫作一本千篇一律的書很容易,而要想自出機(jī)抒,形成自己的風(fēng)格,并且為讀者認(rèn)可,則是難上加難。而敬彬的系列作品,已經(jīng)形成了自己獨(dú)特的風(fēng)格,并且為廣大技術(shù)愛好者們所喜愛,這不獨(dú)是匠心所在,更是隱現(xiàn)宗師風(fēng)范。
如作者所說,有數(shù)據(jù)庫就有SQL,而SQL又因其靈活、復(fù)雜,而讓眾多應(yīng)用系統(tǒng)飽受性能之苦。我一直認(rèn)為,在開發(fā)環(huán)節(jié)提高SQL質(zhì)量才是數(shù)據(jù)庫優(yōu)化的治本良方,SQL審核也是DevOps理念在數(shù)據(jù)庫領(lǐng)域的最佳落地點(diǎn),云和恩墨也在此保持持續(xù)的關(guān)注并研發(fā)了產(chǎn)品。敬彬的新書從SQL入手,以其獨(dú)特的故事演繹法,讓SQL優(yōu)化成為了一種趣味,書中還通過實(shí)例打破了以訛傳訛的種種法則,讓讀者獲得思想上的自由。
這是一本活的書,活躍的思想,活潑的行文,活動(dòng)的二維碼,活靈活現(xiàn)的音視頻,互聯(lián)網(wǎng)時(shí)代,原來書還可以這樣寫。
快點(diǎn)來一起體驗(yàn)吧!
蓋國強(qiáng)
云和恩墨創(chuàng)始人,Oracle ACE總監(jiān),ACOUG主席
致謝
我首先要感謝福富軟件公司,因?yàn)檫@本書的原型,正是公司的認(rèn)證資格課程《基于案例學(xué)SQL優(yōu)化》。公司福富大學(xué)專程請(qǐng)來專業(yè)的企業(yè)內(nèi)訓(xùn)專家為福富內(nèi)訓(xùn)師們做內(nèi)訓(xùn)課程的培訓(xùn)和完善,最終這門課程有幸成為我們公司年度三門精品課程之首。這期間福富研究院的專家們對(duì)本課程進(jìn)行了大量的評(píng)審,并提出了各種寶貴的意見。感謝福富公司!感謝福富大學(xué)和福富研究院!
我要感謝我們項(xiàng)目組團(tuán)隊(duì)的成員,沒有黃锏、榮志等公司杰出的技術(shù)專家和我并肩作戰(zhàn),我也沒有精力寫完這本書。我要感謝姚建藝、鄭清泉、鄭超群等,他們?yōu)槲覀儓F(tuán)隊(duì)的工作提供了最有力的幫助。要特別感謝我們的楊總,她一如既往的支持、她熱情洋溢的《序》讓我感動(dòng)不已!
我要感謝我弟梁敬弘在本書內(nèi)容上傾注精力。感謝林舒楠、張鳳為本書在視覺設(shè)計(jì)上提供的幫助。感謝謝恒忠在線上拓展方面提供的幫助。謝謝你們的參與!
此外,我要感謝蘇旭暉、盧濤、丁俊等這幾位業(yè)內(nèi)知名的數(shù)據(jù)庫專家對(duì)本書的審核校驗(yàn),感謝博文視點(diǎn)在出版方面的專業(yè)性指導(dǎo)意見。感謝大家的幫助!
最后,我要感謝我親愛的家人,謝謝你們的支持!
梁敬彬
2017年4月
前言與意識(shí):從優(yōu)化方法到全書脈絡(luò)
嘆IT之一入深似海
傳說:一入IT深似海,從此菜鳥淚成河。
老師,搞IT真有傳說中的這么慘嗎,那我從此要珍愛生命、遠(yuǎn)離IT了。
我們慢慢聊吧。話說這時(shí)代啊,應(yīng)該是最好的時(shí)代了。知識(shí)的獲取相當(dāng)便利,基本上沒有什么知識(shí)點(diǎn)是搜索引擎搜不到的;此外,現(xiàn)在的技術(shù)書籍、教學(xué)視頻也非常豐富。除了自學(xué)手段外,我們甚至還可以在論壇上提問,或者參加各種線上和線下的培訓(xùn)。當(dāng)今時(shí)代,IT學(xué)習(xí)成本越來越低,門檻似乎一點(diǎn)都不高!
對(duì)啊,那咋說深似海淚成河呢?
其實(shí)這話也是有道理的。我們來說說這個(gè)時(shí)代的IT系統(tǒng),其和從前也大不相同了,現(xiàn)在對(duì)外的IT系統(tǒng)大多需要同時(shí)支持電腦終端和手機(jī)終端(手機(jī)終端進(jìn)一步分為Android和iOS等操作系統(tǒng)),此外還要考慮各個(gè)接口,如關(guān)聯(lián)業(yè)務(wù)接口、短信接口、微信接口、公安接口、銀行接口……系統(tǒng)顯然比以前更復(fù)雜了。這意味著系統(tǒng)開發(fā)在功能實(shí)現(xiàn)方面的難度更大了,而系統(tǒng)實(shí)現(xiàn)難度大又意味著對(duì)IT開發(fā)人員要求更高了!
嗯,好像是這樣。
其實(shí)不止是IT系統(tǒng)功能實(shí)現(xiàn)的難度變大。你想想看,現(xiàn)在幾乎人人都有手機(jī),手機(jī)端的接入就意味著成千上萬的人可以隨時(shí)隨地拿起手機(jī)訪問系統(tǒng),這給系統(tǒng)帶來了可怕的訪問量。此外,不可避免地會(huì)出現(xiàn)同一時(shí)刻大量用戶同時(shí)訪問某應(yīng)用的景象,這又帶來了巨大的并發(fā)量。因此系統(tǒng)如果沒有良好的性能規(guī)劃,很容易垮掉。所以說IT開發(fā)人員的壓力不僅是實(shí)現(xiàn)難,還會(huì)遭遇性能瓶頸。當(dāng)然,IT運(yùn)維人員的壓力更大,因?yàn)榧偃缦到y(tǒng)有問題,他們首當(dāng)其沖。
哇,好像還真是如此,聽得我手心出汗了。
前面我們談到了功能實(shí)現(xiàn)困難,又提到性能瓶頸壓力,現(xiàn)在我再提一點(diǎn),即定位困難。還記得之前我說的接口嗎?隨著時(shí)代的發(fā)展,各種IT應(yīng)用已從孤島走向關(guān)聯(lián)。比如你的系統(tǒng)是計(jì)費(fèi)系統(tǒng),當(dāng)要對(duì)用戶進(jìn)行計(jì)費(fèi)時(shí),你可能要從客服系統(tǒng)中獲取用戶的套餐等資料,或許還要去網(wǎng)廳系統(tǒng)完成……這下問題來了,假如應(yīng)用有故障,你知道問題出在哪嗎?是你自己的系統(tǒng)出問題,還是接口的系統(tǒng)出問題?再比如,你好不容易定位出是自己系統(tǒng)的問題,那請(qǐng)問,到底是數(shù)據(jù)庫、前端應(yīng)用還是中間件的問題呢?
老師,有沒有手帕,我擦擦臉上的汗。
假如你已經(jīng)知道系統(tǒng)的問題出在數(shù)據(jù)庫。那請(qǐng)問,是SQL還是其他問題,你如何定位,如何判斷?再假如你通過努力判斷出是SQL問題,那該如何優(yōu)化,是動(dòng)手改寫呢,還是不用改寫,加加索引啥的……
老師,要考慮的方方面面太多了,看來我是把IT系統(tǒng)想簡單了。
剛討論的話題,放在以前,是基本不用擔(dān)憂的,這是時(shí)代高速發(fā)展帶來的問題。接下來你換一個(gè)角度想想,這個(gè)時(shí)代越來越多的人依賴IT系統(tǒng),你的系統(tǒng)一旦出現(xiàn)問題,多少用戶會(huì)受到影響?這個(gè)時(shí)代越來越多的IT系統(tǒng)之間有關(guān)聯(lián),你的系統(tǒng)一旦出現(xiàn)問題,多少別人的系統(tǒng)會(huì)受到影響?怎么樣,是不是又感受到另一層面的壓力了。
哇,看來這時(shí)代IT人尤其是IT菜鳥的日子真的不好過啊!一入IT深似海,從此菜鳥淚成河。
結(jié)論:當(dāng)今時(shí)代的IT系統(tǒng)復(fù)雜度高、數(shù)據(jù)量和并發(fā)量大、關(guān)聯(lián)性強(qiáng),無論是定位解決故障還是應(yīng)用開發(fā)維護(hù),難度都比較大,并不是一件輕松的事情。
贊IT之SQL地位高
你也吟上這詩了,別傷感,這不也有好事嘛,我之前就說過如今學(xué)習(xí)比以前容易很多。
說的也是,我都忘記了,還好還有這點(diǎn)值得安慰。
真是如此嗎?好吧,以IT學(xué)習(xí)中的SQL優(yōu)化為例,你知道如何進(jìn)行學(xué)習(xí)嗎?
這個(gè)我知道,SQL優(yōu)化主要是看執(zhí)行計(jì)劃,比如發(fā)現(xiàn)是不合理的全表掃描,就設(shè)法轉(zhuǎn)成索引掃描等。
說得有點(diǎn)簡單啊。其實(shí)SQL本不需要優(yōu)化,就是因?yàn)榍懊嫖覀兯f的當(dāng)今IT系統(tǒng)復(fù)雜度高、訪問量和并發(fā)量都大,而數(shù)據(jù)又是IT應(yīng)用中訪問的熱點(diǎn),因此這些壓力自然就體現(xiàn)在IT系統(tǒng)對(duì)應(yīng)的數(shù)據(jù)庫模塊上,所以SQL需要優(yōu)化。
哦,原來如此,明白了。
任何IT系統(tǒng),數(shù)據(jù)都是核心,同時(shí)也是訪問和展現(xiàn)的熱點(diǎn),脫離數(shù)據(jù)庫的IT項(xiàng)目幾乎不存在,甚至可以說幾乎沒有不需要進(jìn)行數(shù)據(jù)庫操作的編程人員,而能與數(shù)據(jù)庫進(jìn)行無縫交互的就只有SQL了。此外,SQL是一種學(xué)起來非常容易的“傻瓜語言”,隨便一個(gè)where條件就是一個(gè)需求實(shí)現(xiàn),基本上新手級(jí)別的開發(fā)人員坐下來看看簡單語法即可編寫SQL,如果有3天時(shí)間邊做邊學(xué),基本上所有SQL都會(huì)編寫了。用我本人的例子來說吧,有人忽然問我學(xué)SQL開發(fā)學(xué)了多久,我?guī)缀跏潜灸馨銖淖炖锩俺鲆痪洌篠QL開發(fā),我有花時(shí)間學(xué)嗎,寫SQL難道不是自然而然就會(huì)了嗎?
正因?yàn)镾QL如此重要,學(xué)習(xí)成本又如此之低,同時(shí)與IT系統(tǒng)中不可或缺的數(shù)據(jù)庫交互起來渾然天成,所以幾乎所有Java、C等開發(fā)人員都能較熟練應(yīng)用數(shù)據(jù)庫SQL開發(fā)技術(shù)。這導(dǎo)致應(yīng)用SQL開發(fā)的人在數(shù)量上異常龐大,簡單地說,就是所有前后端程序開發(fā)人員和IT運(yùn)維人員以及數(shù)據(jù)庫開發(fā)人員的總和!
于是在高訪問量、高并發(fā)的IT系統(tǒng)數(shù)據(jù)庫模塊中,平均每秒運(yùn)行成千上萬條SQL的場景已成常態(tài)。在這種情況下,這些SQL如果運(yùn)行較慢,便容易迅速拖垮整個(gè)IT系統(tǒng),因此SQL優(yōu)化就變得特別重要了。此外,由于SQL過多,不可能僅靠一兩個(gè)SQL專家筋疲力盡地調(diào)優(yōu),我們便可以高枕無憂了。最有效的方式是,每個(gè)SQL編寫人員自己要有SQL優(yōu)化的意識(shí)和本領(lǐng)!
老師,我在項(xiàng)目組里做Java開發(fā),確實(shí)也涉及大量的SQL開發(fā),您說得沒錯(cuò),我也感覺SQL開發(fā)特簡單,不過我的SQL經(jīng)常跑得很慢,您說SQL優(yōu)化好學(xué)嗎?
結(jié)論:數(shù)據(jù)是IT系統(tǒng)的核心、重中之重,而SQL是數(shù)據(jù)交互的必然手段,所以SQL的應(yīng)用非常廣泛,使用人群數(shù)量也非常龐大,因此SQL的重要性不言而喻!
涌SQL之優(yōu)化淚水
SQL優(yōu)化肯定比SQL編寫本身要難很多,但也存在一些優(yōu)化的基礎(chǔ)知識(shí),如SQL執(zhí)行計(jì)劃、索引原理,等等。這些都比編寫SQL本身要復(fù)雜得多,因此要成為SQL優(yōu)化高手僅知道一些優(yōu)化基礎(chǔ)知識(shí)是遠(yuǎn)遠(yuǎn)不夠的,還需要經(jīng)驗(yàn)的沉淀,并且要轉(zhuǎn)化成你的方法論。
老師,您能否舉例說明一下需要什么經(jīng)驗(yàn)嗎?
不妨我回答得更有趣點(diǎn)吧,先給你說幾個(gè)SQL優(yōu)化的小故事,其中奧妙我們后續(xù)探討。
太好了!
嗯,你邊聽邊思考。故事1:話說某天上午小王被告知某系統(tǒng)的一個(gè)菜單訪問非常慢,于是他開始介入優(yōu)化,他跟蹤到該菜單調(diào)用的具體SQL,接下來他通過觀察該SQL的執(zhí)行計(jì)劃發(fā)現(xiàn)該SQL訪問某張表時(shí)沒走索引,覺得該表應(yīng)該加一個(gè)索引,他花了整整1個(gè)小時(shí)發(fā)現(xiàn)這個(gè)問題后非常興奮,于是馬上動(dòng)手開始建索引了。建索引大概花費(fèi)了幾分鐘時(shí)間,隨后他發(fā)現(xiàn)SQL走索引了,并且真的快了許多。于是測試一下該菜單,果然快了不少。故事1講完了。
啥,講完了,太短了吧,您這說的是優(yōu)化成功案例嗎?
是否成功一會(huì)兒再下結(jié)論,接下來說故事2。話說小王優(yōu)化效果杠杠的,正自鳴得意時(shí),被告知雖然這個(gè)菜單變快了,不過剛才持續(xù)幾分鐘時(shí)間出現(xiàn)訪問該菜單一直報(bào)錯(cuò)的情況,隨后正常。
老師,這啥意思,為啥應(yīng)用程序會(huì)出錯(cuò),怎么就恢復(fù)了?您故事2講完了嗎,怎么您的故事都這么短啊?
嗯,現(xiàn)在開始說第3個(gè)故事了。當(dāng)天下午小王又接到電話,被告知那菜單訪問又慢了。小王有點(diǎn)吃驚,于是趕緊登錄系統(tǒng)運(yùn)行該SQL,發(fā)現(xiàn)確實(shí)變慢了,不過奇怪的是該SQL正常走索引,沒什么問題啊,小王很是郁悶。正在他束手無策之時(shí),小王又接到電話,說該菜單又快了。暈,他現(xiàn)在可是啥都沒做,這是咋回事?當(dāng)晚,小王輾轉(zhuǎn)反側(cè),無心睡眠。第2天小王又接到電話……他崩潰了。
好可憐啊。然后呢?
繼續(xù)第4個(gè)故事。話說小王崩潰之后無法正常工作,于是領(lǐng)導(dǎo)把這難題交給其他人處理了,小王得知后滿血復(fù)活再度投入工作中。幾天后小王又迎來一個(gè)新任務(wù),開發(fā)項(xiàng)目組中有一條SQL很慢,希望能優(yōu)化一下。小王看了一眼覺得寫得歪瓜裂棗樣很不舒服,于是挽起袖子對(duì)SQL進(jìn)行重寫,改改改!
然后呢?
小王改好后,滿懷期待的開發(fā)組對(duì)新的SQL一運(yùn)行,發(fā)現(xiàn)跑得比之前的SQL還要慢很多!
可憐,小王又崩潰了吧,接下來呢?
嗯,說故事5吧。在小王再度崩潰之前,公司的SQL優(yōu)化大師老丁正好路過,他分析了之后,建議將SQL語句涉及的某表的外鍵加上索引。后來大家照辦了,果然性能迅速提升!老丁告訴小王,優(yōu)化前可通過各種手段先觀察觀察SQL涉及的表結(jié)構(gòu)、索引等,看它們有無不合理之處,急于動(dòng)手改造SQL太盲目了,是沒有抓住主要矛盾的體現(xiàn),而且改代碼需要測試、打補(bǔ)丁、上線,也是一件很辛苦的事。小王頻頻點(diǎn)頭,謹(jǐn)記老丁教誨。
看來小王成長了。
是嗎?那我們繼續(xù)說故事6。
一周后小王又面對(duì)一條SQL需要優(yōu)化,這次他不動(dòng)手改寫了,嘗試了加索引,又嘗試了調(diào)整表結(jié)構(gòu),結(jié)果提升效果非常不明顯……
然后呢,又崩潰了?
好在老丁又及時(shí)出現(xiàn)了,他這次沒有修改表結(jié)構(gòu),而是和開發(fā)人員進(jìn)行了半小時(shí)的交談,然后居然對(duì)SQL進(jìn)行重寫,改改改!然后 SQL就變得飛快了。小王傻眼了,不是說盡量不著急先動(dòng)手改SQL嗎?怎么老丁一看到這SQL就改改改。悲催啊,該怎么做才是對(duì)的!讓小王悲催的還不止這個(gè),老丁的新SQL看上去并不是很復(fù)雜,可是小王居然看不懂老丁為什么能這么改寫。
沒錯(cuò),看不懂!他看不懂老丁寫什么,也完全不理解新舊SQL的等價(jià)性。
可憐的人!老師,我覺得不是“一入IT深似海,從此菜鳥淚成河。”而是“一入SQL深似海,從此優(yōu)化淚成河。”
結(jié)論:SQL優(yōu)化不是一件容易的事,明明優(yōu)化后變快了,結(jié)果不一會(huì)兒又慢了。有時(shí)不改寫可以解決問題,有時(shí)又必須要改寫才能解決問題。讓人難以適應(yīng)。
析SQL之悲催故事
你故事聽完了,啥感想,就是覺得小王好慘,優(yōu)化很難嗎?
嗯,差不多吧。
好吧,讓我來解讀一下這些故事吧。故事1里小王能定位到具體SQL,并且能根據(jù)SQL執(zhí)行計(jì)劃進(jìn)行SQL優(yōu)化,這至少說明了小王還是掌握了一定的SQL優(yōu)化基礎(chǔ)技能的,否則估計(jì)執(zhí)行計(jì)劃是什么都沒有聽過。不過接下來的故事2和故事3說明他是失敗的。為啥呢?那是因?yàn)樗?jīng)驗(yàn)太少,同時(shí)也缺乏由經(jīng)驗(yàn)轉(zhuǎn)換而成的做事方法論。
我是怎么下的這個(gè)結(jié)論呢?你注意到?jīng)],小王他接到電話后就開始動(dòng)手優(yōu)化了。他難道不應(yīng)該多問一句這問題是一直以來就存在呢,還是今天忽然出現(xiàn)的。
老師,問這有啥用呢?
如果是第一次出現(xiàn),你可能就會(huì)關(guān)注一下是否昨晚系統(tǒng)做了啥動(dòng)作,比如昨晚打了一個(gè)補(bǔ)丁,這補(bǔ)丁引發(fā)這次故障的可能性就非常大,于是目標(biāo)就很清晰了。在實(shí)在無法解決的情況下,回退補(bǔ)丁也是一個(gè)思路。而如果是經(jīng)常有這故障,那應(yīng)該有其他同事處理應(yīng)對(duì)過,獲取他們之前的分析成果,或者收集之前的日志和現(xiàn)在進(jìn)行比對(duì),這些難道對(duì)小王沒幫助嗎?
老師,事實(shí)上是不是因?yàn)橥砩洗蜓a(bǔ)丁導(dǎo)致的?
你可以認(rèn)為是,也可以認(rèn)為不是。我說明一下,這幾個(gè)故事沒有真相,只是解讀一下。真相不重要,你猜測的過程就是你進(jìn)步的過程。另外這里小王是加了一個(gè)索引,你覺得這個(gè)動(dòng)作是對(duì)的還是錯(cuò)的?
老師,我覺得應(yīng)該是錯(cuò)的,因?yàn)樵诘?個(gè)故事里,他加索引后,系統(tǒng)雖然前期變快,但是后來又慢了。我覺得這個(gè)加的索引沒有用,或者至少是沒有解決全部問題。不過我就是奇怪為啥時(shí)快時(shí)慢?
這沒啥奇怪的,我們還是進(jìn)行假設(shè)。你不覺得可能有這么一種情況,此時(shí)整個(gè)系統(tǒng)都非常地慢,根本不只是這個(gè)菜單慢。求助者沒有提出其他模塊慢或許只是因?yàn)樗綍r(shí)僅用這個(gè)菜單,那你想想,如果整個(gè)平臺(tái)都癱瘓了,局部能快起來嗎?
哦,這我怎么一點(diǎn)都沒想到啊!
嗯,我只是說可能性。那為什么整個(gè)數(shù)據(jù)庫都慢?可能性更多了,比如數(shù)據(jù)庫主機(jī)上某些應(yīng)用程序耗盡了主機(jī)的CPU、內(nèi)存等資源,數(shù)據(jù)庫運(yùn)行在這臺(tái)主機(jī)上,覆巢之下安有完卵? 接下來解釋為啥忽快忽慢問題,正常啊,如果這些害人的應(yīng)用程序有時(shí)運(yùn)行,有時(shí)結(jié)束,結(jié)束時(shí)數(shù)據(jù)庫不就正常了?
原來如此啊,第3個(gè)故事里的小王崩潰得好冤啊,如果知道事實(shí)的真相,他把數(shù)據(jù)庫主機(jī)的程序停了或者優(yōu)化了或者移到別的地方去,就解決問題了。
你的這個(gè)解決方案非常棒,不過別忘了我這里不說真相,一切都是可能性解讀。當(dāng)然這些可能性猜測是基于經(jīng)驗(yàn)和推理的,也不是完全沒依據(jù)的。另外,故事2里描述菜單曾經(jīng)出錯(cuò)了幾分鐘,你注意到并思考過為什么了嗎?
有的,不過這是為啥呢?
你沒注意到建索引也是幾分鐘時(shí)間嗎?幾乎可以肯定地說,是這個(gè)建索引動(dòng)作導(dǎo)致的故障。因?yàn)榻ㄋ饕龝?huì)鎖全表,這時(shí)候更新數(shù)據(jù)肯定會(huì)失敗。小王犯了一個(gè)大錯(cuò),在業(yè)務(wù)高峰期做DDL操作,嚴(yán)重地影響了生產(chǎn),問題解決者成了麻煩制造者。這故事2倒是不需要推測的,真相一定如此。
哇,這么嚴(yán)重的錯(cuò)誤原來是小王一手造成的,我還真沒想到。
嗯,再說故事4吧,小王動(dòng)手改改改,然后效果差差差,這里我們可以解讀到什么呢?那就是解決問題要有目的性,不能沒找到真正原因盲目動(dòng)手。你看他覺得SQL寫得不好,就改。實(shí)際上應(yīng)該觀察慢在什么地方,比如可以通過執(zhí)行計(jì)劃看出最大的開銷在某全表掃描上,而該全表掃描完全可以通過索引減少訪問路徑,這時(shí)加索引就可以解決問題,改寫SQL不可能解決問題的。
哦,確實(shí)如此。
接下來,在故事5里,老丁果然只是增加了索引后就解決了性能問題。優(yōu)化SQL不一定非要改寫才可以優(yōu)化,有時(shí)根據(jù)數(shù)據(jù)庫的體系邏輯結(jié)構(gòu)不改寫SQL也可完成優(yōu)化。改寫SQL的代價(jià)也更高,因?yàn)楝F(xiàn)實(shí)中如果你要改SQL肯定需要經(jīng)過測試、打補(bǔ)丁、上線等多個(gè)過程,不可能直接就在生產(chǎn)中修改。
最后看故事6,小王學(xué)習(xí)老丁只調(diào)整參數(shù)進(jìn)行SQL優(yōu)化。接下來劇情反轉(zhuǎn)了,小王學(xué)老丁不改,效果差差差。而老丁則動(dòng)手改改改,效果又是杠杠的。小王欲哭無淚,不知自己該如何做了。其實(shí)這里小王生搬硬套了,他沒有找到本質(zhì)原因,比如此時(shí)可能是由于冗長的寫法導(dǎo)致表訪問了多次,而老王改寫SQL將表訪問次數(shù)大幅度降低下來。這時(shí)不改寫是無法優(yōu)化的。又或者是老丁根據(jù)業(yè)務(wù)需求,砍掉了某些多余的邏輯,這就更需要改寫SQL了。
哦,老師您總結(jié)得很到位啊!
由于不改寫通常來說比改寫高效,而不改寫的優(yōu)化一般都和數(shù)據(jù)庫的體系邏輯架構(gòu)有關(guān)。因此我們需要認(rèn)真學(xué)習(xí)這部分基礎(chǔ)知識(shí),這也就是老師的SQL優(yōu)化課程中為什么會(huì)涉及這部分知識(shí)的原因。不過能不改寫優(yōu)化固然好,有時(shí)等價(jià)改寫也是必需的,而且改寫其實(shí)分成兩個(gè)部分:一個(gè)是等價(jià)改寫;一個(gè)是根據(jù)業(yè)務(wù)改寫。比如小王看某SQL寫得很不順眼,然后動(dòng)手改改改,這顯然是等價(jià)改寫。而老丁和開發(fā)人員交談了半個(gè)多小時(shí),改造后的SQL連小王都看不明白,這就很可能是根據(jù)業(yè)務(wù)改寫的。
明白了,原來如此。
業(yè)務(wù)改寫是優(yōu)化的最高境界,老丁通過和開發(fā)人員交流后發(fā)掘出真正的需求,然后寫出來的代碼表面上看和舊代碼邏輯完全不等價(jià),實(shí)際卻等價(jià)。
哦,老師您能否解釋一下什么叫真正需求?
好吧,還是講生動(dòng)點(diǎn)的例子吧。從前我曾經(jīng)講過一個(gè)《小余買魚》的故事。小余媽媽一個(gè)勁地讓小余買魚招待客人,條件不允許的時(shí)候還堅(jiān)持如此。后來小余讓媽媽用冰箱里的牛肉來代替魚,媽媽也猛然醒悟了,她忘記了需求的本質(zhì)是做美味給大家分享。站在做美味這角度上看,去老遠(yuǎn)的地方買魚和拿冰箱里的牛肉,又有什么區(qū)別呢?
我明白了,沒有提煉到這層需求的人,真的很難理解吃牛肉和吃水煮魚其實(shí)是一樣的,代碼改寫前后表面上有這么大差距,也難怪小王會(huì)大惑不解。
是的,這里順便再說一點(diǎn),小王看不懂老丁寫的SQL,也可能是因?yàn)槔隙∮昧四承┛赡苄⊥鯖]見過的SQL語法來改寫,我們這里稱之為高級(jí)SQL。比如WITH子句、樹形遞歸、分析函數(shù),等等。
哦,好想見識(shí)一下。
結(jié)論:其實(shí)這一節(jié)想說的就是,做事要有方法論,要先整體后局部,解決問題要注重效率,先盡量考慮不改寫的優(yōu)化,再考慮改寫的優(yōu)化。而不改寫的優(yōu)化靠的是體系結(jié)構(gòu)知識(shí)的沉淀,而改寫則要考慮邏輯等價(jià)改寫和業(yè)務(wù)改寫兩大思路,其中業(yè)務(wù)改寫是SQL優(yōu)化的最高境界。另外還是要有一定的知識(shí)沉淀,高級(jí)SQL的語法也要掌握,其在很多場合下能幫上我們大忙。
推規(guī)范流程之必要
其實(shí)小王的系列故事還暴露了他身上一個(gè)非常重要的缺陷,那就是做事缺乏流程、缺乏規(guī)范。先不說解決問題的方法論,小王在系統(tǒng)中建了索引后導(dǎo)致系統(tǒng)出現(xiàn)問題,就是犯了一個(gè)不規(guī)范操作的低級(jí)錯(cuò)誤。這應(yīng)該在DBA的工作流程中是明確禁止操作的。當(dāng)然小王有權(quán)限做這件事也是值得深究的,這種權(quán)限是不是要管控得更嚴(yán)格一些?這里涉及了作業(yè)流程規(guī)范。
接下來小王手忙腳亂地進(jìn)行優(yōu)化,是不是都很有序?他要花一小時(shí)時(shí)間才定位到某處需要建立索引,如果建索引有依據(jù)的規(guī)范并且能快速被體檢報(bào)告診斷出來,他需要花一小時(shí)嗎?這里涉及了數(shù)據(jù)庫的設(shè)計(jì)規(guī)范。
故事中還涉及SQL改寫優(yōu)化的過程,如果性能低下的SQL在運(yùn)行之前能被事先撈取出來,則很多故障就能避免。這里涉及SQL寫法的規(guī)范。
規(guī)范不僅重要,我們更要主動(dòng)去履行。如果我們能一鍵發(fā)現(xiàn)權(quán)限不當(dāng)、數(shù)據(jù)庫設(shè)計(jì)不良、SQL寫法糟糕的問題,那規(guī)范就容易遵守,而不是停留在嘴上。不過放心,我們的數(shù)據(jù)庫整體診斷工具,涵蓋了這里大部分的規(guī)范檢查。
結(jié)論:不成規(guī)矩,無以成方圓,如果能制定一定的規(guī)范并進(jìn)行有效的檢查,系統(tǒng)的性能問題必然會(huì)大幅減少。這里有一個(gè)好消息,就是這些要點(diǎn)大多都涵蓋進(jìn)筆者的一鍵獲取數(shù)據(jù)庫整體信息的腳本中了。
梁敬彬,福富研究院副理事長、公司四星級(jí)內(nèi)訓(xùn)師。不僅是公司特級(jí)專家也是國內(nèi)一線知名數(shù)據(jù)庫專家,其個(gè)人及團(tuán)隊(duì)在數(shù)據(jù)庫優(yōu)化和培訓(xùn)領(lǐng)域有著豐富的經(jīng)驗(yàn)、過硬的質(zhì)量和良好的口碑。多次應(yīng)邀擔(dān)任國內(nèi)外數(shù)據(jù)庫大會(huì)的演講嘉賓,在業(yè)界有著廣泛的影響力。著有多本暢銷數(shù)據(jù)庫技術(shù)書籍,其代表作《收獲,不止Oracle》已成為數(shù)據(jù)庫領(lǐng)域有口皆碑的經(jīng)典書籍,《收獲,不止SQL優(yōu)化》即將開創(chuàng)一個(gè)新的里程碑。
梁敬弘,清華大學(xué)計(jì)算機(jī)系博士畢業(yè),在計(jì)算機(jī)領(lǐng)域和金融領(lǐng)域皆有建樹,擁有多項(xiàng)計(jì)算機(jī)相關(guān)核心專利技術(shù)的同時(shí),還擁有金融行業(yè)的CFP等高級(jí)認(rèn)證。現(xiàn)就職于華夏銀行總行。
第1章 全局在胸——用工具對(duì)SQL整體優(yōu)化 1
1.1 都有哪些性能工具 1
1.1.1 不同調(diào)優(yōu)場景分析 2
1.1.2 不同場景對(duì)應(yīng)工具 2
1.2 整體性能工具的要點(diǎn) 4
1.2.1 五大性能報(bào)告的獲取 5
1.2.2 五大報(bào)告關(guān)注的要點(diǎn) 10
1.3 案例的分享與交流 18
1.3.1 和并行等待有關(guān)的案例 18
1.3.2 和熱塊競爭有關(guān)的案例 19
1.3.3 和日志等待有關(guān)的案例 20
1.3.4 新疆某系統(tǒng)的前臺(tái)優(yōu)化 20
1.3.5 浙江某系統(tǒng)的調(diào)優(yōu)案例 21
1.4 本章總結(jié)延伸與習(xí)題 21
1.4.1 總結(jié)延伸 21
1.4.2 習(xí)題訓(xùn)練 23
第2章 風(fēng)馳電掣——有效縮短SQL優(yōu)化過程 24
2.1 SQL調(diào)優(yōu)時(shí)間都去哪兒了 25
2.1.1 不善于批處理頻頻忙交互 25
2.1.2 無法抓住主要矛盾瞎折騰 25
2.1.3 未能明確需求目標(biāo)白費(fèi)勁 26
2.1.4 沒有分析操作難度亂調(diào)優(yōu) 26
2.2 如何縮短SQL調(diào)優(yōu)時(shí)間 27
2.2.1 先獲取有助調(diào)優(yōu)的數(shù)據(jù)庫整體信息 27
2.2.2 快速獲取SQL運(yùn)行臺(tái)前信息 27
2.2.3 快速拿到SQL關(guān)聯(lián)幕后信息 28
2.3 從案例看快速SQL調(diào)優(yōu) 29
2.3.1 獲取數(shù)據(jù)庫整體的運(yùn)行情況 29
2.3.2 獲取SQL的各種詳細(xì)信息 29
2.4 本章總結(jié)延伸與習(xí)題 32
2.4.1 總結(jié)延伸 32
2.4.2 習(xí)題訓(xùn)練 33
第3章 循規(guī)蹈矩——如何讀懂SQL執(zhí)行計(jì)劃 34
3.1 執(zhí)行計(jì)劃分析概述 35
3.1.1 SQL執(zhí)行計(jì)劃是什么 35
3.1.2 統(tǒng)計(jì)信息用來做什么 36
3.1.3 數(shù)據(jù)庫統(tǒng)計(jì)信息的收集 37
3.1.4 數(shù)據(jù)庫的動(dòng)態(tài)采樣 37
3.1.5 獲取執(zhí)行計(jì)劃的方法(6種武器) 40
3.2 讀懂執(zhí)行計(jì)劃的關(guān)鍵 48
3.2.1 解釋經(jīng)典執(zhí)行計(jì)劃方法 49
3.2.2 總結(jié)說明 55
3.3 從案例辨別低效SQL 55
3.3.1 從執(zhí)行計(jì)劃讀出效率 56
3.3.2 執(zhí)行計(jì)劃效率總結(jié) 60
3.4 本章習(xí)題、總結(jié)與延伸 60
第4章 運(yùn)籌帷幄——左右SQL執(zhí)行計(jì)劃妙招 62
4.1 控制執(zhí)行計(jì)劃的方法綜述 63
4.1.1 控制執(zhí)行計(jì)劃的意義 63
4.1.2 控制執(zhí)行計(jì)劃的思路 64
4.2 從案例探索其方法及意義 65
4.2.1 HINT的思路 65
4.2.2 非HINT方式的執(zhí)行計(jì)劃改變 72
4.2.3 執(zhí)行計(jì)劃的固定 100
4.3 本章習(xí)題、總結(jié)與延伸 102
第5章 且慢,感受體系結(jié)構(gòu)讓SQL飛 103
5.1 體系結(jié)構(gòu)知識(shí) 104
5.1.1 組成 104
5.1.2 原理 104
5.1.3 體會(huì) 105
5.2 體系與SQL優(yōu)化 106
5.2.1 與共享池相關(guān) 107
5.2.2 數(shù)據(jù)緩沖相關(guān) 111
5.2.3 日志歸檔相關(guān) 116
5.3 擴(kuò)展優(yōu)化案例 118
5.3.1 與共享池相關(guān) 118
5.3.2 數(shù)據(jù)緩沖相關(guān) 122
5.3.3 日志歸檔相關(guān) 126
5.4 本章習(xí)題、總結(jié)與延伸 130
第6章 且慢,體驗(yàn)邏輯結(jié)構(gòu)讓SQL飛 132
6.1 邏輯結(jié)構(gòu) 132
6.2 體系細(xì)節(jié)與SQL優(yōu)化 133
6.2.1 Block 133
6.2.2 Segment與extent 137
6.2.3 Tablespace 139
6.2.4 rowid 139
6.3 相關(guān)優(yōu)化案例分析 140
6.3.1 塊的相關(guān)案例 141
6.3.2 段的相關(guān)案例 144
6.3.3 表空間的案例 148
6.3.4 rowid 151
6.4 本章習(xí)題、總結(jié)與延伸 153
第7章 且慢,探尋表的設(shè)計(jì)讓SQL飛 154
7.1 表設(shè)計(jì) 154
7.1.1 表的設(shè)計(jì) 155
7.1.2 其他補(bǔ)充 155
7.2 表設(shè)計(jì)與SQL優(yōu)化 156
7.2.1 表的設(shè)計(jì) 156
7.2.2 其他補(bǔ)充 179
7.3 相關(guān)優(yōu)化案例分析 184
7.3.1 分區(qū)表相關(guān)案例 185
7.3.2 全局臨時(shí)表案例 190
7.3.3 監(jiān)控異常的表設(shè)計(jì) 195
7.3.4 表設(shè)計(jì)優(yōu)化相關(guān)案例總結(jié) 199
7.4 本章習(xí)題、總結(jié)與延伸 199
第8章 且慢,學(xué)習(xí)索引如何讓SQL飛 200
8.1 索引知識(shí)要點(diǎn)概述 201
8.1.1 索引結(jié)構(gòu)的推理 201
8.1.2 索引特性的提煉 204
8.2 索引的SQL優(yōu)化 206
8.2.1 經(jīng)典三大特性 207
8.2.2 組合索引選用 217
8.2.3 索引掃描類型的分類與構(gòu)造 219
8.3 索引相關(guān)優(yōu)化案例 225
8.3.1 三大特性的相關(guān)案例 225
8.3.2 組合索引的經(jīng)典案例 231
8.4 本章習(xí)題、總結(jié)與延伸 234
第9章 且慢,弄清索引之阻礙讓SQL飛 235
9.1 索引的不足之處 235
9.1.1 索引的各種開銷 236
9.1.2 索引使用失效 236
9.2 感受美好索引另一面 237
9.2.1 索引各種開銷 237
9.2.2 索引使用失效 243
9.2.3 索引取舍控制 246
9.3 從案例看索引各種恨 248
9.3.1 索引的開銷 248
9.3.2 索引去哪兒了 253
9.3.3 索引的取舍 267
9.4 本章習(xí)題、總結(jié)與延伸 269
第10章 且慢,其他索引應(yīng)用讓SQL飛 270
10.1 其他索引的總體概述 270
10.1.1 位圖索引 271
10.1.2 函數(shù)索引 271
10.1.3 反向鍵索引 272
10.1.4 全文索引 272
10.2 走進(jìn)其他索引的世界 272
10.2.1 位圖索引 273
10.2.2 函數(shù)索引 278
10.2.3 反向鍵索引 282
10.2.4 全文索引 282
10.3 其他索引的相關(guān)案例 285
10.3.1 位圖索引 286
10.3.2 函數(shù)索引 288
10.3.3 反向鍵索引 297
10.3.4 全文索引 299
10.4 本章習(xí)題、總結(jié)與延伸 300
第11章 且慢,表連接的秘密讓SQL飛 302
11.1 三大經(jīng)典表連接概要說明 302
11.2 各類型表連接的知識(shí)要點(diǎn) 303
11.2.1 從表的訪問次數(shù)探索 304
11.2.2 表驅(qū)動(dòng)順序與性能 308
11.2.3 表連接是否有排序 311
11.2.4 各連接的使用限制 314
11.2.5 三大表連接的特性總結(jié) 317
11.3 從案例學(xué)表連接優(yōu)化要點(diǎn) (三刀三斧四式走天下) 317
11.3.1 一次Nested Loops Join的優(yōu)化全過程 318
11.3.2 一次Hash Join 的 優(yōu)化全過程 320
11.3.3 一次 Merge Sort Join 的優(yōu)化全過程 324
11.3.4 一次統(tǒng)計(jì)信息收集不準(zhǔn)確引發(fā)的NL性能瓶頸 329
11.4 本章習(xí)題、總結(jié)與延伸 332
第12章 動(dòng)手,經(jīng)典等價(jià)改寫讓SQL飛 333
12.1 設(shè)法減少訪問路徑 333
12.1.1 Case When改造 334
12.1.2 Rownum分頁改寫 337
12.1.3 Hint直接路徑改造 338
12.1.4 只取你所需的列 339
12.1.5 避免或者減少遞歸調(diào)用 341
12.1.6 ROWID優(yōu)化應(yīng)用 347
12.2 設(shè)法避免外因影響 350
12.2.1 Hint改寫確保執(zhí)行計(jì)劃正確 350
12.2.2 避免子查詢的錯(cuò)誤執(zhí)行計(jì)劃 350
12.2.3 所在環(huán)境的資源不足等問題 351
12.3 本章習(xí)題、總結(jié)與延伸 351
第13章 動(dòng)手,過程函數(shù)優(yōu)化讓SQL飛 352
13.1 PL/SQL優(yōu)化重點(diǎn) 353
13.1.1 定義類型的優(yōu)化 353
13.1.2 PL/SQL的集合優(yōu)化 355
13.1.3 PL/SQL的游標(biāo)合并 361
13.1.4 動(dòng)態(tài)SQL 364
13.1.5 使用10046 trace跟蹤PL/SQL 368
13.2 PL/SQL優(yōu)化其他相關(guān)擴(kuò)展 369
13.2.1 編譯無法成功 369
13.2.2 通用腳本分享 370
13.3 本章習(xí)題、總結(jié)與延伸 380
第14章 動(dòng)手,高級(jí)寫法應(yīng)用讓SQL飛 381
14.1 具體SQL調(diào)優(yōu)思路 381
14.1.1 改寫SQL調(diào)優(yōu) 382
14.1.2 不改寫SQL調(diào)優(yōu) 382
14.2 高級(jí)SQL介紹與案例 383
14.2.1 GOURP BY的擴(kuò)展 383
14.2.2 INSERT ALL 389
14.2.3 MERGE 392
14.2.4 WITH子句 402
14.3 本章習(xí)題、總結(jié)與延伸 404
第15章 動(dòng)手,分析函數(shù)讓SQL飛 406
15.1 高級(jí)SQL之分析函數(shù) 407
15.1.1 語法概述 407
15.1.2 特別之處 407
15.2 分析函數(shù)詳解與案例 409
15.2.1 學(xué)習(xí)詳解 410
15.2.2 案例分享 417
15.3 本章習(xí)題、總結(jié)與延伸 432
第16章 動(dòng)手,把握需求改寫讓SQL飛 433
16.1 考慮需求最小化 434
16.2 千萬弄清SQL改造的等價(jià)性 434
16.2.1 看似等價(jià)的寫法,其實(shí)不等價(jià) 435
16.2.2 看似不等價(jià)的寫法,其實(shí)等價(jià) 438
16.3 開發(fā)設(shè)計(jì)應(yīng)用中的需求 439
16.3.1 界面權(quán)限設(shè)計(jì)優(yōu)化 439
16.3.2 界面匯總與展現(xiàn) 439
16.3.3 界面實(shí)時(shí)刷新改良 439
16.3.4 目錄樹菜單的優(yōu)化 440
16.4 場景選擇的經(jīng)典案例之誰是Count(*)之王 440
16.4.1 優(yōu)化過程 440
16.4.2 優(yōu)化總結(jié) 445
16.5 本章習(xí)題、總結(jié)與延伸 446
第17章 總結(jié)與延伸:從勿信訛傳到洞若觀火 447
17.1 SQL優(yōu)化的各個(gè)誤區(qū) 447
17.1.1 COUNT(*)與COUNT(列)的傳言 447
17.1.2 談SQL編寫順序之流言蜚語 451
17.1.3 IN與EXISTS之爭 455
17.1.4 總結(jié)探討 457
17.2 誤區(qū)背后的話題擴(kuò)展 457
17.2.1 話題擴(kuò)展之等價(jià)與否優(yōu)先 457
17.2.2 話題擴(kuò)展之顛覆誤區(qū)觀點(diǎn) 458
17.3 全書完,致讀者 461