自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

不得不看,只有專家才知道的17個(gè)SQL查詢提速秘訣!

譯文
數(shù)據(jù)庫 其他數(shù)據(jù)庫
通常,開發(fā)人員找到自己青睞的方法,而懶得研究其他方法。這也許是缺乏教育的表現(xiàn),或者開發(fā)人員沒有認(rèn)識(shí)到自己何時(shí)做錯(cuò)了。也許針對(duì)一組本地測(cè)試數(shù)據(jù),查詢運(yùn)行起來順暢,但是換成生產(chǎn)級(jí)系統(tǒng),表現(xiàn)就差強(qiáng)人意。

【51CTO.com快譯】除非你遵循本文介紹的這些技巧,否則很容易編寫出減慢查詢速度或鎖死數(shù)據(jù)庫的數(shù)據(jù)庫代碼。

[[218119]]

由于數(shù)據(jù)庫領(lǐng)域仍相對(duì)不成熟,每個(gè)平臺(tái)上的 SQL 開發(fā)人員都在苦苦掙扎,一次又一次犯同樣的錯(cuò)誤。

當(dāng)然,數(shù)據(jù)庫廠商在取得一些進(jìn)展,并繼續(xù)在竭力處理較重大的問題。

無論 SQL 開發(fā)人員在 SQL Server、Oracle、DB2、Sybase、MySQL,還是在其他任何關(guān)系數(shù)據(jù)庫平臺(tái)上編寫代碼,并發(fā)性、資源管理、空間管理和運(yùn)行速度都仍困擾著他們。

問題的一方面是,不存在什么靈丹妙藥;針對(duì)幾乎每條***實(shí)踐,我都可以舉出至少一個(gè)例外。

通常,開發(fā)人員找到自己青睞的方法,而懶得研究其他方法。這也許是缺乏教育的表現(xiàn),或者開發(fā)人員沒有認(rèn)識(shí)到自己何時(shí)做錯(cuò)了。也許針對(duì)一組本地測(cè)試數(shù)據(jù),查詢運(yùn)行起來順暢,但是換成生產(chǎn)級(jí)系統(tǒng),表現(xiàn)就差強(qiáng)人意。

我沒有期望 SQL 開發(fā)人員成為管理員,但他們?cè)诰帉懘a時(shí)必須考慮到生產(chǎn)級(jí)環(huán)境的問題。如果他們?cè)陂_發(fā)初期不這么做,數(shù)據(jù)庫管理員后期會(huì)讓他們返工,遭殃的就是用戶。

我們說調(diào)優(yōu)數(shù)據(jù)庫既是門藝術(shù),又是門科學(xué),這是有道理的,因?yàn)楹苌儆腥孢m用的硬性規(guī)則。你在一個(gè)系統(tǒng)上解決的問題在另一個(gè)系統(tǒng)上不是問題,反之亦然。

說到調(diào)優(yōu)查詢,沒有正確的答案,但這并不意味著就此應(yīng)該放棄。你可以遵循以下17條原則,有望收到很好的效果。

不要用 UPDATE 代替 CASE

這個(gè)問題很常見,卻很難發(fā)覺,許多開發(fā)人員常常忽視這個(gè)問題,原因是使用 UPDATE 再自然不過,這似乎合乎邏輯。

以這個(gè)場(chǎng)景為例:你把數(shù)據(jù)插入一個(gè)臨時(shí)表中,如果另一個(gè)值存在,需要它顯示某個(gè)值。

也許你從 Customer 表中提取記錄,想把訂單金額超過 100000 美元的客戶標(biāo)記為“Preferred”。

因而,你將數(shù)據(jù)插入到表中,運(yùn)行 UPDATE 語句,針對(duì)訂單金額超過 100000 美元的任何客戶,將 CustomerRank 這一列設(shè)為“Preferred”。

問題是,UPDATE 語句記入日志,這就意味著每次寫入到表中,要寫入兩次。

解決辦法:在 SQL 查詢中使用內(nèi)聯(lián) CASE 語句,這檢驗(yàn)每一行的訂單金額條件,并向表寫入“Preferred”標(biāo)記之前,設(shè)置該標(biāo)記,這樣處理性能提升幅度很驚人。

不要盲目地重用代碼

這個(gè)問題也很常見,我們很容易拷貝別人編寫的代碼,因?yàn)槟阒浪塬@取所需的數(shù)據(jù)。

問題是,它常常獲取過多你不需要的數(shù)據(jù),而開發(fā)人員很少精簡(jiǎn),因此到頭來是一大堆數(shù)據(jù)。

這通常表現(xiàn)為 WHERE 子句中的一個(gè)額外外連接或額外條件。如果你根據(jù)自己的確切要求精簡(jiǎn)重用的代碼,就能大幅提升性能。

需要幾列,就提取幾列

這個(gè)問題類似第 2 個(gè)問題,但這是列所特有的。很容易用 SELECT* 來編寫所有查詢代碼,而不是把列逐個(gè)列出來。

問題同樣是,它提取過多你不需要的數(shù)據(jù),這個(gè)錯(cuò)誤我見過無數(shù)次了。開發(fā)人員對(duì)一個(gè)有 120 列、數(shù)百萬行的表執(zhí)行 SELECT* 查詢,但***只用到其中的三五列。

因此,你處理的數(shù)據(jù)比實(shí)際需要的多得多,查詢返回結(jié)果是個(gè)奇跡。你不僅處理過多不需要的數(shù)據(jù),還奪走了其他進(jìn)程的資源。

不要查詢兩次(double-dip)

這是我看到好多人犯的另一個(gè)錯(cuò)誤:寫入存儲(chǔ)過程,從一個(gè)有數(shù)億行的表中提取數(shù)據(jù)。

開發(fā)人員想提取住在加利福尼亞州,年收入高于 4 萬美元的客戶信息。于是,他查詢住在加利福尼亞州的客戶,把查詢結(jié)果放到一個(gè)臨時(shí)表中。

然后再來查詢年收入高于 4 萬美元的客戶,把那些結(jié)果放到另一個(gè)臨時(shí)表中。***他連接這兩個(gè)表,獲得最終結(jié)果。

你是在逗我吧?這應(yīng)該用一次查詢來完成,相反你對(duì)一個(gè)超大表查詢兩次。別犯傻了:大表盡量只查詢一次,你會(huì)發(fā)現(xiàn)存儲(chǔ)過程執(zhí)行起來快多了。

一種略有不同的場(chǎng)景是,某個(gè)過程的幾個(gè)步驟需要大表的一個(gè)子集時(shí),這導(dǎo)致每次都要查詢大表。

想避免這個(gè)問題,只需查詢這個(gè)子集,并將它持久化存儲(chǔ)到別處,然后將后面的步驟指向這個(gè)比較小的數(shù)據(jù)集。

知道何時(shí)使用臨時(shí)表

這個(gè)問題解決起來要麻煩一點(diǎn),但效果顯著。在許多情況下可以使用臨時(shí)表,比如防止對(duì)大表查詢兩次。還可以使用臨時(shí)表,大幅減少連接大表所需的處理能力。

如果你必須將一個(gè)表連接到大表,該大表上又有條件,只需將大表中所需的那部分?jǐn)?shù)據(jù)提取到臨時(shí)表中,然后再與該臨時(shí)表連接,就可以提升查詢性能。

如果存儲(chǔ)過程中有幾個(gè)查詢需要對(duì)同一個(gè)表執(zhí)行類似的連接,這同樣大有幫助。

預(yù)暫存數(shù)據(jù)

這是我***聊的話題之一,因?yàn)檫@是一種經(jīng)常被人忽視的老方法。

如果你有一個(gè)報(bào)表或存儲(chǔ)過程(或一組)要對(duì)大表執(zhí)行類似的連接操作,通過提前連接表,并將它們持久化存儲(chǔ)到一個(gè)表中來預(yù)暫存數(shù)據(jù),就可以對(duì)你大有幫助。

現(xiàn)在,報(bào)表可以針對(duì)該預(yù)暫存表來運(yùn)行,避免大連接。你并非總是可以使用這個(gè)方法,但一旦用得上,你會(huì)發(fā)現(xiàn)這絕對(duì)是節(jié)省服務(wù)器資源的好方法。

請(qǐng)注意:許多開發(fā)人員避開這個(gè)連接問題的做法是,將注意力集中在查詢本身上,根據(jù)連接創(chuàng)建只讀視圖,那樣就不必一次又一次鍵入連接條件。

但這種方法的問題是,仍要為需要它的每個(gè)報(bào)表運(yùn)行查詢。如果預(yù)暫存數(shù)據(jù),你只要運(yùn)行一次連接(比如說報(bào)表前 10 分鐘),別人就可以避免大連接了。

你不知道我有多喜歡這一招,在大多數(shù)環(huán)境下,有些常用表一直被連接起來,所以沒理由不能先預(yù)暫存起來。

批量刪除和更新

這是另一個(gè)經(jīng)常被忽視的技巧,如果你操作不當(dāng),刪除或更新來自大表的大量數(shù)據(jù)可能是一場(chǎng)噩夢(mèng)。

問題是,這兩種語句都作為單一事務(wù)來運(yùn)行。如果你需要終結(jié)它們,或者它們?cè)趫?zhí)行時(shí)系統(tǒng)遇到了問題,系統(tǒng)必須回滾(roll back)整個(gè)事務(wù),這要花很長的時(shí)間。

這些操作在持續(xù)期間還會(huì)阻塞其他事務(wù),實(shí)際上給系統(tǒng)帶來了瓶頸,解決辦法就是,小批量刪除或更新。

這通過幾個(gè)方法來解決問題:

  • 無論事務(wù)因什么原因而被終結(jié),它只有少量的行需要回滾,那樣數(shù)據(jù)庫聯(lián)機(jī)返回快得多。
  • 小批量事務(wù)被提交到磁盤時(shí),其他事務(wù)可以進(jìn)來處理一些工作,因而大大提高了并發(fā)性。

同樣,許多開發(fā)人員一直固執(zhí)地認(rèn)為:這些刪除和更新操作必須在同一天完成。事實(shí)并非總是如此,如果你在歸檔更是如此。

如果你需要延長該操作,可以這么做,小批量有助于實(shí)現(xiàn)這點(diǎn);如果你花更長的時(shí)間來執(zhí)行這些密集型操作,切忌拖慢系統(tǒng)的運(yùn)行速度。

使用臨時(shí)表來提高游標(biāo)性能

如果可能的話,***避免游標(biāo)。游標(biāo)不僅存在速度問題,而速度問題本身是許多操作的一大問題,還會(huì)導(dǎo)致你的操作長時(shí)間阻塞其他操作,這大大降低了系統(tǒng)的并發(fā)性。

然而無法總是避免使用游標(biāo),避免不了使用游標(biāo)時(shí),可以改而對(duì)臨時(shí)表執(zhí)行游標(biāo)操作,以此擺脫游標(biāo)引發(fā)的性能問題。

不妨以查閱一個(gè)表,基于一些比較結(jié)果來更新幾個(gè)列的游標(biāo)為例。你也許可以將該數(shù)據(jù)放入臨時(shí)表中,然后針對(duì)臨時(shí)表進(jìn)行比較,而不是針對(duì)活動(dòng)表進(jìn)行比較。

然后你可以針對(duì)小得多,鎖定時(shí)間很短的活動(dòng)表運(yùn)行單一的 UPDATE 語句。

進(jìn)行這樣的數(shù)據(jù)修改可大大提高并發(fā)性。***我要說,你根本不需要使用游標(biāo),總是會(huì)有一種基于集合的解決方法。

不要嵌套視圖

視圖也許很方便,不過使用視圖時(shí)要小心。

雖然視圖有助于將龐大查詢遮掩起來、無須用戶操心,并實(shí)現(xiàn)數(shù)據(jù)訪問標(biāo)準(zhǔn)化,但你很容易發(fā)現(xiàn)自己陷入這種困境:視圖 A 調(diào)用視圖 B,視圖 B 調(diào)用視圖 C,視圖 C 又調(diào)用視圖 D,這就是所謂的嵌套視圖。

這會(huì)導(dǎo)致嚴(yán)重的性能問題,尤其是這兩方面:

  • 返回的數(shù)據(jù)很有可能比你需要的多得多。
  • 查詢優(yōu)化器將放棄并返回一個(gè)糟糕的查詢方案。

我遇到過喜歡嵌套視圖的客戶,這個(gè)客戶有一個(gè)視圖用于幾乎所有數(shù)據(jù),因?yàn)樗袃蓚€(gè)重要的連接。

問題是,視圖返回的一個(gè)列里面居然有 2MB 大小的文檔,有些文檔甚至更大。

在運(yùn)行的幾乎每一次查詢中,這個(gè)客戶要在網(wǎng)絡(luò)上為每一行至少多推送 2MB 的數(shù)據(jù)。自然,查詢性能糟糕透頂。

沒有一個(gè)查詢實(shí)際使用該列!當(dāng)然,該列被埋在七個(gè)視圖的深處,要找出來都很難。我從視圖中刪除該文檔列后,***查詢的時(shí)間從 2.5 小時(shí)縮短至 10 分鐘。

我***層層解開了嵌套視圖(有幾個(gè)不必要的連接和列),并寫了一個(gè)普通的查詢,結(jié)果同樣這個(gè)查詢的時(shí)間縮短至不到 1 秒。

使用表值函數(shù)

這是一直以來我***用的技巧之一,因?yàn)樗侵挥袑<也胖赖哪欠N秘訣。

在查詢的 SELECT 列表中使用標(biāo)量函數(shù)時(shí),該函數(shù)因結(jié)果集中的每一行而被調(diào)用,這會(huì)大幅降低大型查詢的性能。

然而可以將標(biāo)量函數(shù)轉(zhuǎn)換成表值函數(shù),然后在查詢中使用 CROSS APPLY,就可以大幅提升性能,這個(gè)奇妙的技巧可以顯著提升性能。

使用分區(qū)避免移動(dòng)大型數(shù)據(jù)

不是每個(gè)人都能利用依賴 SQL Server Enterprise 中分區(qū)的這個(gè)技巧,但是對(duì)于能利用它的人來說,這個(gè)技巧很棒。

大多數(shù)人沒有意識(shí)到 SQL Server 中的所有表都是分區(qū)的。如果你喜歡,可以把一個(gè)表分成多個(gè)分區(qū),但即使簡(jiǎn)單的表也從創(chuàng)建那一刻起就分區(qū)了。

然而,它們是作為單個(gè)分區(qū)創(chuàng)建的。如果你在運(yùn)行 SQL Server Enterprise,已經(jīng)可以隨時(shí)享用分區(qū)表的優(yōu)點(diǎn)了。

這意味著你可以使用 SWITCH 之類的分區(qū)功能,歸檔來自倉庫加載的大量數(shù)據(jù)。

舉個(gè)實(shí)際例子,去年我碰到過這樣一個(gè)客戶:該客戶需要將數(shù)據(jù)從當(dāng)日的表復(fù)制到歸檔表中;那樣萬一加載失敗,公司可以迅速用當(dāng)日的表來恢復(fù)。

由于各種原因,無法每次將表的名稱改來改去,所以公司每天在加載前將數(shù)據(jù)插入到歸檔表中,然后從活動(dòng)表刪除當(dāng)日的數(shù)據(jù)。

這個(gè)過程一開始很順利,但一年后,復(fù)制每個(gè)表要花 1 個(gè)半小時(shí),每天要復(fù)制幾個(gè)表,問題只會(huì)越來越糟。

解決辦法是拋棄 INSERT 和 DELETE 進(jìn)程,使用 SWITCH 命令。

SWITCH 命令讓該公司得以避免所有寫入,因?yàn)樗鼘㈨撁娣峙浣o了歸檔表。

這只是更改了元數(shù)據(jù),SWITCH 運(yùn)行平均只要兩三秒鐘,如果當(dāng)前加載失敗,你可以通過 SWTICH 將數(shù)據(jù)切換回到原始表。

如果你非要用 ORM,請(qǐng)使用存儲(chǔ)過程

ORM 是我經(jīng)常炮轟的對(duì)象之一。簡(jiǎn)而言之,別使用 ORM(對(duì)象關(guān)系映射器)。

ORM 會(huì)生成世界上最糟糕的代碼,我遇到的幾乎每個(gè)性能問題都是由它引起的。

相比知道自己在做什么的人,ORM 代碼生成器不可能寫出一樣好的 SQL。但是如果你使用 ORM,那就編寫自己的存儲(chǔ)過程,讓 ORM 調(diào)用存儲(chǔ)過程,而不是寫自己的查詢。

我知道使用 ORM 的種種理由,也知道開發(fā)人員和經(jīng)理都喜歡 ORM,因?yàn)樗鼈冇兄诋a(chǎn)品迅速投向市場(chǎng)。但是如果你看一下查詢對(duì)數(shù)據(jù)庫做了什么,就會(huì)發(fā)現(xiàn)代價(jià)太高了。

存儲(chǔ)過程有許多優(yōu)點(diǎn),首先,你在網(wǎng)絡(luò)上推送的數(shù)據(jù)少得多。如果有一個(gè)長查詢,那么它可能在網(wǎng)絡(luò)上要往返三四趟才能讓整個(gè)查詢到達(dá)數(shù)據(jù)庫服務(wù)器。

這不包括服務(wù)器將查詢重新組合起來并運(yùn)行所花的時(shí)間;另外考慮這點(diǎn):查詢可能每秒運(yùn)行幾次或幾百次。

使用存儲(chǔ)過程可大大減少傳輸?shù)牧髁浚驗(yàn)榇鎯?chǔ)過程調(diào)用總是短得多。另外,存儲(chǔ)過程在 Profiler 或其他任何工具中更容易追蹤。

存儲(chǔ)過程是數(shù)據(jù)庫中的實(shí)際對(duì)象,這意味著相比臨時(shí)查詢(ad-hoc query),獲取存儲(chǔ)過程的性能統(tǒng)計(jì)數(shù)字要容易得多,因而發(fā)現(xiàn)性能問題、查明異常情況也要容易得多。

此外,存儲(chǔ)過程參數(shù)化更一致,這意味著你更可能會(huì)重用執(zhí)行方案,甚至處理緩存問題,要查明臨時(shí)查詢的緩存問題很難。

有了存儲(chǔ)過程,處理邊界情況(edge case),甚至增加審計(jì)或變更鎖定行為變得容易多了。存儲(chǔ)過程可以處理困擾臨時(shí)查詢的許多任務(wù)。

幾年前,我妻子理清了 Entity Framework 的一個(gè)兩頁長的查詢,該查詢花了 25 分鐘來運(yùn)行。

她化繁為簡(jiǎn),將這個(gè)大型查詢改寫為 SELECT COUNT(*) fromT1,這不是開玩笑。

那些只是要點(diǎn),我知道,許多 .NET 程序員認(rèn)為業(yè)務(wù)邏輯不適宜放在數(shù)據(jù)庫中,這大錯(cuò)特錯(cuò)。

如果將業(yè)務(wù)邏輯放在應(yīng)用程序的前端,僅僅為了比較就得將所有數(shù)據(jù)傳送一遍,那樣不會(huì)有好的性能。

我有個(gè)客戶將所有邏輯保存在數(shù)據(jù)庫的外面,在前端處理一切。該公司將成千上萬行數(shù)據(jù)發(fā)送到前端,以便能夠運(yùn)用業(yè)務(wù)邏輯,并顯示所需的數(shù)據(jù)。

這個(gè)過程花了 40 分鐘,我把存儲(chǔ)過程放在后端,讓它從前端調(diào)用;頁面在三秒鐘內(nèi)加載完畢。

當(dāng)然,有時(shí)邏輯適宜放在前端上,有時(shí)適宜放在數(shù)據(jù)庫中,但是 ORM 總是讓我上火。

不要對(duì)同一批次的許多表執(zhí)行大型操作

這個(gè)似乎很明顯,但實(shí)則不然。我會(huì)用另一個(gè)鮮活的例子,因?yàn)樗苷f明問題。

我有一個(gè)系統(tǒng)存在大量的阻塞,眾多操作處于停滯狀態(tài)。結(jié)果查明,每天運(yùn)行幾次的刪除例程在刪除顯式事務(wù)中 14 個(gè)表的數(shù)據(jù)。處理一個(gè)事務(wù)中的所有 14 個(gè)表意味著,鎖定每個(gè)表,直到所有刪除完成。

解決辦法就是,將每個(gè)表的刪除分解成單獨(dú)的事務(wù),以便每個(gè)刪除事務(wù)只鎖定一個(gè)表。

這解放了其他表,緩解了阻塞,讓其他操作得以繼續(xù)運(yùn)行。你總是應(yīng)該把這樣的大事務(wù)分解成單獨(dú)的小事務(wù),以防阻塞。

不要使用觸發(fā)器

這個(gè)與前一個(gè)大體一樣,但還是值得一提。觸發(fā)器的問題:無論你希望觸發(fā)器執(zhí)行什么,都會(huì)在與原始操作同一個(gè)的事務(wù)中執(zhí)行。

如果你寫一個(gè)觸發(fā)器,以便更新 Orders 表中的行時(shí)將數(shù)據(jù)插入到另一個(gè)表中,會(huì)同時(shí)鎖定這兩個(gè)表,直到觸發(fā)器執(zhí)行完畢。

如果你需要在更新后將數(shù)據(jù)插入到另一個(gè)表中,要將更新和插入放入到存儲(chǔ)過程中,并在單獨(dú)的事務(wù)中執(zhí)行。

如果你需要回滾,就很容易回滾,不必同時(shí)鎖定這兩個(gè)表。與往常一樣,事務(wù)要盡量短小,每次不要鎖定多個(gè)資源。

不要在 GUID 上聚類

這么多年后,我難以相信我們居然還在為這個(gè)問題而苦惱。但我仍然每年遇到至少兩次聚類 GUID。

GUID(全局唯一標(biāo)識(shí)符)是一個(gè) 16 字節(jié)的隨機(jī)生成的數(shù)字。相比使用一個(gè)穩(wěn)定增加的值(比如 DATE 或 IDENTITY),按此列對(duì)你表中的數(shù)據(jù)進(jìn)行排序?qū)е卤硭槠斓枚唷?/p>

幾年前我做過一項(xiàng)基準(zhǔn)測(cè)試,我將一堆數(shù)據(jù)插入到一個(gè)帶聚類 GUID 的表中,將同樣的數(shù)據(jù)插入到另一個(gè)帶 IDENTITY 列的表中。

GUID 表碎片化極其嚴(yán)重,僅僅過了 15 分鐘,性能就下降了幾千個(gè)百分點(diǎn)。

5 小時(shí)后,IDENTITY 表的性能才下降了幾個(gè)百分點(diǎn),這不僅僅適用于 GUID,它適用于任何易失性列。

如果只需查看數(shù)據(jù)是否存在,就不要計(jì)數(shù)行

這種情況很常見,你需要查看數(shù)據(jù)存在于表格中,根據(jù)這番檢查的結(jié)果,你要執(zhí)行某個(gè)操作。

我經(jīng)常見到有人執(zhí)行 SELECT COUNT(*)FROMdbo.T1來檢查該數(shù)據(jù)是否存在:

  1. SET @CT=(SELECT COUNT(*) FROM 
  2. dbo.T1); 
  3.    If@CT>0 
  4.    BEGIN 
  5.    <Do something> 
  6. END 

這完全沒必要,如果你想檢查數(shù)據(jù)是否存在,只要這么做:

  1. If EXISTS (SELECT 1 FROM dbo.T1) 
  2.  BEGIN 
  3.  <Do something> 
  4.  END 

不要計(jì)數(shù)表中的一切,只要取回你找到的***行。SQL Server 聰明得很,會(huì)正確使用 EXISTS,第二段代碼返回結(jié)果超快。

表越大,這方面的差距越明顯。在你的數(shù)據(jù)變得太大之前做正確的事情。調(diào)優(yōu)數(shù)據(jù)庫永不嫌早。

實(shí)際上,我只是在我的其中一個(gè)生產(chǎn)數(shù)據(jù)庫上運(yùn)行這個(gè)例子,針對(duì)一個(gè)有 2.7 億行的表。

***次查詢用時(shí) 15 秒,包含 456197 個(gè)邏輯讀取,第二次查詢不到 1 秒就返回結(jié)果,只包含 5 個(gè)邏輯讀取。

然而如果你確實(shí)需要計(jì)數(shù)表的行數(shù),表又很大,另一種方法就是從系統(tǒng)表中提取,SELECT rows fromsysindexes 將為你獲得所有索引的行數(shù)。

又由于聚類索引代表數(shù)據(jù)本身,所以只要添加 WHERE indid = 1,就能獲得表行,然后只需包含表名稱即可。

所以,***的查詢是:

  1. SELECT rows from sysindexes where object_name(id)='T1'and indexid =1 

在我 2.7 億行的表中,不到 1 秒就返回結(jié)果,只有 6 個(gè)邏輯讀取,現(xiàn)在性能不一樣了。

不要進(jìn)行逆向搜索

以簡(jiǎn)單的查詢 SELECT * FROMCustomers WHERE RegionID <> 3 為例。

你不能將索引與該查詢結(jié)合使用,因?yàn)樗悄嫦蛩阉?,需要借助表掃描來逐行比較。

如果你需要執(zhí)行這樣的任務(wù),可能發(fā)現(xiàn)如果重寫查詢以使用索引,性能會(huì)好得多。

該查詢很容易重寫,就像這樣:

  1. SELECT * FROM Customers WHERE RegionID<3 UNION ALL SELECT * FROM Customers WHERE RegionID 

這個(gè)查詢將使用索引,所以如果你的數(shù)據(jù)集很大,其性能會(huì)遠(yuǎn)勝過表掃描版本。

當(dāng)然,沒有什么是那么容易的,也許性能更糟,所以使用之前先試一下。它***管用,雖然涉及太多的因素。

***,我意識(shí)到這個(gè)查詢違反了第 4 條規(guī)則:不要查詢兩次,但這也表明沒有硬性規(guī)則。雖然我們?cè)谶@里查詢兩次,但這么做是為了避免開銷很大的表掃描。

你無法一直運(yùn)用所有這些技巧,但如果牢記它們,有一天你會(huì)用它們來解決一些大問題。

要記住的最重要一點(diǎn)是,別將我說的話當(dāng)成教條。在你的實(shí)際環(huán)境中試一下,同樣的解決辦法不是在每種情況下都管用,不過我排查糟糕的性能時(shí)一直使用這些方法,而且屢試不爽。

【51CTO譯稿,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文譯者和出處為51CTO.com】

 

責(zé)任編輯:武曉燕 來源: 51CTO技術(shù)棧
相關(guān)推薦

2010-07-23 18:39:52

SQL Server游

2014-10-30 13:38:55

編程算法程序員

2014-08-13 13:22:28

CA TechnoloDevOps

2012-06-21 09:49:39

2010-05-26 15:58:52

MySQL遠(yuǎn)程連接

2010-05-10 13:01:03

OracleDBA面試

2010-05-21 09:40:57

MySQL出錯(cuò)代碼列表

2010-05-25 09:58:43

MySQL數(shù)據(jù)庫

2015-09-22 10:03:25

大數(shù)據(jù)秘訣

2015-09-23 10:27:04

大數(shù)據(jù)秘訣

2019-12-10 15:30:27

SaaSIaaS云計(jì)算

2010-04-21 17:19:29

Oracle創(chuàng)建

2010-05-19 16:39:11

MySQL查詢

2020-09-19 17:59:21

sorted()Python函數(shù)

2010-08-18 11:36:40

DB2簡(jiǎn)史

2010-05-18 10:34:29

MySQL數(shù)據(jù)庫備份

2010-05-26 13:14:22

MySQL錯(cuò)誤解決方案

2010-08-02 11:01:29

DB2 Resotre

2017-05-17 14:46:22

容器DockerLinux

2010-05-05 11:30:21

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)