日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

寫有效率的SQL查詢(I)

系統(tǒng) 2182 0

大型系統(tǒng)的生產(chǎn)環(huán)境,一般情況下,我們?cè)u(píng)價(jià)一條查詢是否有效率,更多的是關(guān)注邏輯 IO( 至于為什么,回頭補(bǔ)一篇 ) 。我們常說,“要建彪悍的索引”、“要寫高效的 SQL ”,其實(shí)最終目的就是在相同結(jié)果集情況下,盡可能減少邏輯 IO

1.1 ???? where 條件的列上都得有統(tǒng)計(jì)信息。

沒統(tǒng)計(jì)信息 SQLServer 就無法估算不同查詢計(jì)劃開銷優(yōu)劣,而只能采用最穩(wěn)妥的 Scan (不管是 table scan 還是 clustered index scan )。一般情況下我們不會(huì)犯這種錯(cuò)誤—— where 條件里不使用非索引列是個(gè)常識(shí)。索引上的統(tǒng)計(jì)信息是無法刪除的。

1.2 ???? 盡量不使用不等于( != )或者 NOT 邏輯運(yùn)算符。

這條規(guī)則被廣為傳頌,原因據(jù)聯(lián)機(jī)文檔和百敬同學(xué)的書講,也是 SQLServer 無法評(píng)估不同查詢計(jì)劃開銷的優(yōu)劣。但是 SqlServer2k5 聰明了很多,試驗(yàn)發(fā)現(xiàn)盡管用了 != 或者 not ,查詢還是會(huì)被優(yōu)化。如下:

create table tb1

(

??? col1 int identity ( 1 , 1 ) primary key ,

??? col2 int not null,

??? col3 varchar ( 64 ) not null

)

create index ix_tb1_col2 on tb1

(

??? col2

)

create index ix_tb1_col3 on tb1

(

??? col3

)

declare @f int

set @f = 0

while @f < 9999

begin

??? insert into tb1 ( col2 , col3 ) values ( 1 , 'ssdd' )

??? set @f = @f + 1

end

insert into tb1 ( col2 , col3 ) values ( 0 , 'aadddd' )

insert into tb1 ( col2 , col3 ) values ( 2 , 'bbddd' )

insert into tb1 ( col2 , col3 ) values ( 3 , 'bbaaddddddaa' )

通過上述代碼,各位可以看到數(shù)據(jù)分布。 col2 值為 1 的有 9999 條; col2 值為 0 2 3 的分別有 1 條。

按照本條規(guī)則, != NOT 帶來的應(yīng)該是個(gè) scan 操作,但實(shí)際情況是:
??? 寫有效率的SQL查詢(I)
寫有效率的SQL查詢(I)

SQL2k5 很聰明,它依據(jù)統(tǒng)計(jì)信息分析得出來,應(yīng)該采用 index seek 而不是 index scan 。( 稍微解釋解釋 index seek index scan :索引是一顆 B 樹, index seek 是查找從 B 樹的根節(jié)點(diǎn)開始,一級(jí)一級(jí)找到目標(biāo)行。 index scan 則是從左到右,把整個(gè) B 樹遍歷一遍。假設(shè)唯一的目標(biāo)行位于索引樹(假設(shè)是非聚集索引,樹深度 2 ,葉節(jié)點(diǎn)占用 k 頁物理存儲(chǔ))最右的葉節(jié)點(diǎn)上(如上例)。 index seek 引起的 IO 4 ,而 index scan 引起的 IO K ,性能差別巨大。關(guān)于索引,可以仔細(xì)讀讀聯(lián)機(jī)文檔關(guān)于物理數(shù)據(jù)庫體系結(jié)構(gòu)部分 )。

1.3 ???? 查詢條件中不要包含運(yùn)算

這些運(yùn)算包括字符串連接(如: select * from Users where UserName + ‘pig’ = ‘ 張三 pig’ ),通配符在前面的 Like 運(yùn)算(如: select * from tb1 where col4 like ‘%aa’ ),使用其他用戶自定義函數(shù)、系統(tǒng)內(nèi)置函數(shù)、標(biāo)量函數(shù)等等(如: select * from UserLog where datepart(dd, LogTime) = 3 )。

???????? SQLServer 在處理以上語句時(shí),一樣沒辦法估算開銷。最終結(jié)果當(dāng)然是 clustered index scan 或者 table scan 了。

1.4 ???? 查詢條件中不要包含同一張表內(nèi)不同列之間的運(yùn)算

所謂的“運(yùn)算”包括加減乘除或通過一些 function (如: select * from tb where col1 – col2 = 1997 ),也包括比較運(yùn)算(如: select * from tb where col1 > col2 )。這種情況下, SQLServer 一樣沒辦法估算開銷。不論 col1 col2 上都有索引還是創(chuàng)建了 col1 col2 上的覆蓋索引還是創(chuàng)建了 col1 include col2 的索引。

但是這種查詢有解決辦法,可以在表上多創(chuàng)建一個(gè)計(jì)算字段,其值設(shè)置為你的“運(yùn)算”結(jié)果,再在該字段上創(chuàng)建一個(gè)索引,就 Ok 了。

?

?

To Be Continue…

(II)中將介紹統(tǒng)計(jì)信息值分布不均勻?qū)Σ樵兊挠绊懞腿绾伪苊膺@些影響,捎帶更多的說說返回多行結(jié)果時(shí),為啥SQLServer有時(shí)會(huì)選擇index seek,而有時(shí)會(huì)選擇index scan。
(III)中主要介紹傳說中的“Foldable”和“NonFoldable”表達(dá)式。并舉例說說所謂的“Nonfoldable"表達(dá)式某些情況下也不是那么可怕。
(IV)中則主要說說在程序中執(zhí)行SQL。如:安全性,拼SQL、參數(shù)化SQL和存儲(chǔ)過程之間對(duì)DB來說有什么區(qū)別,參數(shù)化SQL的一些技巧。捎帶著,會(huì)大概介紹介紹SQLServer的Buffer Pool

寫有效率的SQL查詢(I)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 镶黄旗| 南华县| 左权县| 广东省| 宝清县| 德江县| 根河市| 潜江市| 南平市| 西畴县| 汨罗市| 凌云县| 黄浦区| 青阳县| 大名县| 清远市| 锦屏县| 昭苏县| 芦溪县| 蒙自县| 香河县| 贞丰县| 响水县| 平阳县| 嘉鱼县| 太保市| 象州县| 祁门县| 壶关县| 玉屏| 苏尼特右旗| 石河子市| 澎湖县| 武宣县| 红原县| 福海县| 奎屯市| 肇源县| 昌都县| 方正县| 河北省|