<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 1, 文章 - 44, 評(píng)論 - 2, 引用 - 0
    數(shù)據(jù)加載中……

    常用SQL語(yǔ)句書寫技巧(轉(zhuǎn))

    SQL結(jié)構(gòu)化查詢字符串的改寫,是實(shí)現(xiàn)數(shù)據(jù)庫(kù)查詢性能提升的最現(xiàn)實(shí)、最有效的手段,有時(shí)甚至是唯一的手段,比如在不允許大幅度修改現(xiàn)有數(shù)據(jù)庫(kù)結(jié)構(gòu)的情況下。
    通過(guò)優(yōu)化SQL語(yǔ)句提高查詢性能的關(guān)鍵是:
    ? 根據(jù)實(shí)際需求情況,建立合適的索引;
    ? 使用一切可能的方式去利用好索引,避免全表掃描;
    ? 盡量減少內(nèi)存及數(shù)據(jù)I/O方面的開(kāi)銷

    一、 建立索引
    (一)建立“適當(dāng)”的索引,是快速查詢的基礎(chǔ)。
    索引(index)是除表之外另一重要的、用戶定義的存儲(chǔ)在物理介質(zhì)上的數(shù)據(jù)結(jié)構(gòu)。當(dāng)根據(jù)索引碼的值搜索數(shù)據(jù)時(shí),索引提供了對(duì)數(shù)據(jù)的快速訪問(wèn)。事實(shí)上,沒(méi)有索引,數(shù)據(jù)庫(kù)也能根據(jù)Select語(yǔ)句成功地檢索到結(jié)果,但隨著表變得越來(lái)越大,使用“適當(dāng)”的索引的效果就越來(lái)越明顯。注意,在這句話中,我們用了“適當(dāng)”這個(gè)詞,這是因?yàn)椋绻褂盟饕龝r(shí)不認(rèn)真考慮其實(shí)現(xiàn)過(guò)程,索引既可以提高也會(huì)破壞數(shù)據(jù)庫(kù)的工作性能。
    索引實(shí)際上是一種特殊的目錄,SQL SERVER提供了兩種索引:
    ? 聚集索引(clustered index,也稱聚類索引、簇集索引)
    我們把這種正文內(nèi)容本身就是一種按照一定規(guī)則排列的目錄稱為“聚集索引”。
    例如:
    漢語(yǔ)字典中按拼音查某一個(gè)字,就是使用“聚集索引”,實(shí)際上,你根本用不著查目錄,直接在字典正文里找,就能很快找到需要的漢字(假設(shè)你知道發(fā)音)。
    ? 非聚集索引(nonclustered index,也稱非聚類索引、非簇集索引)
    我們把目錄純粹是目錄,正文純粹是正文的排序方式稱為“非聚集索引”。
    例如:
    漢語(yǔ)字典中按部首查某一個(gè)字,部首目錄和正文一定要刻意的通過(guò)頁(yè)碼才能聯(lián)系到一起,其順序不是天然一致的。

    聚集索引與非聚集索引的最大區(qū)別就在于:聚集索引是對(duì)原數(shù)據(jù)表進(jìn)行排序,因此只要符合索引條件,就能夠直接連續(xù)的讀取數(shù)據(jù)記錄,幾乎可以達(dá)到對(duì)數(shù)據(jù)表的零掃描;而非聚集索引僅僅只是另外建了一張索引表,取數(shù)據(jù)的時(shí)候,從索引表取得結(jié)果后,還需要到指針?biāo)傅臄?shù)據(jù)行讀取相應(yīng)數(shù)據(jù),因此,在性能上,聚集索引會(huì)大大優(yōu)于非聚集索引。
      但是在一張表中,聚集索引只允許一個(gè),是比較寶貴的,因此要盡可能的用于那些使用頻率最高的索引上。 另外,查詢時(shí)必需要用到索引的起始列,否則索引無(wú)效。另外,起始列也必需是使用頻繁的列,那樣的索引性能才會(huì)達(dá)到最優(yōu)化。

    (二)表:何時(shí)應(yīng)使用聚集索引或非聚集索引

    動(dòng)作描述 使用聚集索引 使用非聚集索引
    列經(jīng)常被分組排序 ○ ○
    返回某范圍內(nèi)的數(shù)據(jù) ○
    一個(gè)或極少不同值
    小數(shù)目的不同值 ○
    大數(shù)目的不同值 ○
    頻繁更新的列 ○
    外鍵列 ○ ○
    主鍵列 ○ ○
    頻繁修改索引列 ○

    (三)索引建立的一些注意項(xiàng)
    1、不要把聚集索引浪費(fèi)在主鍵上,除非你只按主鍵查詢
    雖然SQL SERVER默認(rèn)是在主鍵上建立聚集索引的,但實(shí)際應(yīng)用中,這樣做比較浪費(fèi)。通常,我們會(huì)在每個(gè)表中都建立一個(gè)ID列,以區(qū)分每條數(shù)據(jù),并且這個(gè)ID列是自動(dòng)增大的,步長(zhǎng)一般為1。此時(shí),如果我們將這個(gè)列設(shè)為主鍵,SQL SERVER會(huì)將此列默認(rèn)為聚集索引。這樣做有好處,就是可以讓您的數(shù)據(jù)在數(shù)據(jù)庫(kù)中按照ID進(jìn)行物理排序,但這樣做實(shí)用價(jià)值不大。
    從我們前面談到的聚集索引的定義我們可以看出,使用聚集索引的最大好處就是能夠根據(jù)查詢要求,迅速縮小查詢范圍,避免全表掃描。在實(shí)際應(yīng)用中,因?yàn)镮D號(hào)是自動(dòng)生成的,我們并不知道每條記錄的ID號(hào),所以我們很難在實(shí)踐中用ID號(hào)來(lái)進(jìn)行查詢。這就使讓ID號(hào)這個(gè)主鍵作為聚集索引成為一種資源浪費(fèi)。聚集索引相對(duì)與非聚集索引的優(yōu)勢(shì)是很明顯的,而每個(gè)表中只能有一個(gè)聚集索引的規(guī)則,這使得聚集索引變得更加寶貴,應(yīng)該用在其他查詢頻率高的字段上。其次,讓每個(gè)ID號(hào)都不同的字段作為聚集索引也不符合“大數(shù)目的不同值情況下不應(yīng)建立聚合索引”規(guī)則;當(dāng)然,這種情況只是針對(duì)用戶經(jīng)常修改記錄內(nèi)容,特別是索引項(xiàng)的時(shí)候會(huì)負(fù)作用,但對(duì)于查詢速度并沒(méi)有影響。

    2、索引的建立要根據(jù)實(shí)際應(yīng)用需求來(lái)進(jìn)行
    并非是在任何字段上簡(jiǎn)單地建立索引就能提高查詢速度。聚集索引建立的規(guī)則大致是“既不能絕大多數(shù)都相同,又不能只有極少數(shù)相同”。舉個(gè)例子,在公文表的收發(fā)日期字段上建立聚合索引是比較合適的。在政務(wù)系統(tǒng)中,我們每天都會(huì)收一些文件,這些文件的發(fā)文日期將會(huì)相同,在發(fā)文日期上建立聚合索引對(duì)性能的提升應(yīng)該是相當(dāng)大的。在群集索引下,數(shù)據(jù)物理上按順序存于數(shù)據(jù)頁(yè)上,重復(fù)值也排列在一起,因而在范圍查找時(shí),可以先找到這個(gè)范圍的起末點(diǎn),且只在這個(gè)范圍內(nèi)掃描數(shù)據(jù)頁(yè),避免了大范圍掃描,提高了查詢速度。
    另一個(gè)相反的例子:比如在雇員表的“性別”列上只有“男”與“女”兩個(gè)不同值,因此就完全沒(méi)必要建立索引。

    3、在聚集索引中加入所有需要提高查詢速度的字段,形成復(fù)合索引
    根據(jù)一些實(shí)驗(yàn)的結(jié)果,我們可以得出一些可供參考的結(jié)論:
    ? 僅用復(fù)合聚集索引的起始列作為查詢條件和同時(shí)用到復(fù)合聚集索引的全部列的查詢,速度是幾乎一樣的,甚至比后者還要快(在查詢結(jié)果集數(shù)目一樣的情況下);
    ? 僅用復(fù)合聚集索引的非起始列作為查詢條件的話,
    這個(gè)索引是不起任何作用的。
    ? 復(fù)合聚集索引的所有列都用上,而且因?yàn)椴樵儣l件嚴(yán)格,查詢結(jié)果少的話,會(huì)形成“索引覆蓋”,性能可以達(dá)到最優(yōu)。
    ? 最重要的一點(diǎn):無(wú)論是否經(jīng)常使用復(fù)合聚合索引的其他列,其起始列一定要是使用最頻繁的列。

    4.根據(jù)實(shí)踐得出的一些其他經(jīng)驗(yàn),特定情況下有效
    ? 用聚合索引比用不是聚合索引的主鍵速度快;
    ? 用聚合索引比用一般的主鍵作order by速度快,特別是在小數(shù)據(jù)量情況;
    ? 使用聚合索引內(nèi)的時(shí)間段,搜索時(shí)間會(huì)按數(shù)據(jù)占整個(gè)數(shù)據(jù)表的百分比成比例減少,而無(wú)論聚合索引使用了多少個(gè);
    ? 日期列不會(huì)因?yàn)橛蟹置氲妮斎攵鴾p慢查詢速度;
    ? 由于改變一個(gè)表的內(nèi)容,將會(huì)引起索引的變化。頻繁的insert,update,delete語(yǔ)句將導(dǎo)致系統(tǒng)花費(fèi)較大的代價(jià)進(jìn)行索引更新,引起整體性能的下降。一般來(lái)講,在對(duì)查詢性能的要求高于對(duì)數(shù)據(jù)維護(hù)性能要求時(shí),應(yīng)該盡量使用索引,否則,就要慎重考慮一下付出的代價(jià)。在某些極端情況下,可先刪除索引,再對(duì)數(shù)據(jù)庫(kù)表更新大量數(shù)據(jù),最后再重建索引,新建立的索引總是比較好用。

    二、 編寫優(yōu)化的SQL語(yǔ)句,充分利用索引
    下面就某些SQL語(yǔ)句的where子句編寫中需要注意的問(wèn)題作詳細(xì)介紹。在這些where子句中,即使某些列存在索引,但是由于編寫了劣質(zhì)的SQL,系統(tǒng)在運(yùn)行該SQL語(yǔ)句時(shí)也不能使用該索引,而同樣使用全表掃描,這就造成了響應(yīng)速度的極大降低。
    SQL語(yǔ)句在提交給數(shù)據(jù)庫(kù)進(jìn)行操作前,都會(huì)經(jīng)過(guò)查詢分析階段,SQLSERVER內(nèi)置的查詢優(yōu)化器會(huì)分析查詢條件的的每個(gè)部分,并判斷這些條件是否符合掃描參數(shù)(SARG)的標(biāo)準(zhǔn)。只有當(dāng)一個(gè)查詢條件符合SARG的標(biāo)準(zhǔn),才可以通過(guò)預(yù)先設(shè)置的索引,提升查詢性能。
    SARG的定義:用于限制搜索操作的一種規(guī)范,通常是指一個(gè)特定的匹配,一個(gè)確定范圍內(nèi)的匹配或者兩個(gè)以上條件的AND連接。一般形式如下:
    列名 操作符 <常數(shù) 或 變量>

    <常數(shù) 或 變量> 操作符 列名
    列名可以出現(xiàn)在操作符的一邊,而常數(shù)或變量出現(xiàn)在操作符的另一邊。如:
    Name=’張三’
    價(jià)格>5000
    5000<價(jià)格
    Name=’張三’ and 價(jià)格>5000
    如果一個(gè)表達(dá)式不能滿足SARG的形式,那它就無(wú)法限制搜索的范圍了,也就是說(shuō)SQL SERVER必須對(duì)每一行都判斷它是否滿足Where子句中的所有條件,既進(jìn)行全表掃描。所以,一個(gè)索引對(duì)于不滿足SARG形式的表達(dá)式來(lái)說(shuō)是無(wú)用的, 如:當(dāng)查詢條件為“價(jià)格*2 >5000”時(shí),就無(wú)法利用建立在價(jià)格字段上的索引 。
    SQLSERVER內(nèi)置了查詢優(yōu)化器,能將一些條件自動(dòng)轉(zhuǎn)換為符合SARG標(biāo)準(zhǔn),如:將“價(jià)格*2 >5000” 轉(zhuǎn)換為“價(jià)格 >2500/2 ”,以達(dá)到可以使用索引的目的,但這種轉(zhuǎn)化不是100%可靠的,有時(shí)會(huì)有語(yǔ)義上的損失,有時(shí)轉(zhuǎn)化不了。如果對(duì)“查詢優(yōu)化器”的工作原理不是特別了解,寫出的SQL語(yǔ)句可能不會(huì)按照您的本意進(jìn)行查詢。所以不能完全依賴查詢優(yōu)化器的優(yōu)化,建議大家還是利用自己的優(yōu)化知識(shí),盡可能顯式的書寫出符合SARG標(biāo)準(zhǔn)的SQL語(yǔ)句,自行確定查詢條件的構(gòu)建方式,這樣一方面有利于查詢分析器分析最佳索引匹配順序,另一方面也有利于今后重讀代碼。
    介紹完SARG后,我們?cè)俳Y(jié)合一些實(shí)際運(yùn)用中的例子來(lái)做進(jìn)一步的講解:
    1、 Like語(yǔ)句是否屬于SARG取決于使用%通配符的樣式
    如:name like ‘張%’ ,這就屬于SARG
    而:name like ‘%張’ ,就不屬于SARG

    通配符%在字符串首字符的使用會(huì)導(dǎo)致索引無(wú)法使用,雖然實(shí)際應(yīng)用中很難避免這樣用,但還是應(yīng)該對(duì)這種現(xiàn)象有所了解,至少知道此種用法性能是很低下的。
    2、 “非”操作符不滿足SARG形式,使得索引無(wú)法使用
    不滿足SARG形式的語(yǔ)句最典型的情況就是包括非操作符的語(yǔ)句,如:NOT、!=、<>、!<、!>、NOT EXISTS、NOT IN、NOT LIKE等。
    下面是一個(gè)NOT子句的例子:
      ... where not (status ='valid')
      not運(yùn)算符也隱式的包含在另外一些邏輯運(yùn)算符中,比如<>運(yùn)算符。見(jiàn)下例:
      ... where status <>'invalid';

      再看下面這個(gè)例子:
      select * from employee where salary<>3000;
      對(duì)這個(gè)查詢,可以改寫為不使用not:
      select * from employee where salary<3000 or salary>3000;

      雖然這兩種查詢的結(jié)果一樣,但是第二種查詢方案會(huì)比第一種查詢方案更快些。第二種查詢?cè)试S對(duì)salary列使用索引,而第一種查詢則不能使用索引。

    3、 函數(shù)運(yùn)算不滿足SARG形式,使得索引無(wú)法使用
    例:下列SQL條件語(yǔ)句中的列都建有恰當(dāng)?shù)乃饕珗?zhí)行速度卻非常慢:
    select * from record where substring(card_no,1,4)=′5378′(13秒)
    select * from record where amount/30< 1000(11秒)
    select * from record where convert(char(10),date,112)=′19991201′(10秒)
    分析:
    where子句中對(duì)列的任何操作結(jié)果都是在SQL運(yùn)行時(shí)逐列計(jì)算得到的,因此它不得不進(jìn)行全表掃描,而沒(méi)有使用該列上面的索引;如果這些結(jié)果在查詢編譯時(shí)就能得到,那么就可以被SQL優(yōu)化器優(yōu)化,使用索引,避免表搜索,因此將SQL重寫成下面這樣:
    select * from record where card_no like ′5378%′(< 1秒)
    select * from record where amount < 1000*30(< 1秒)
    select * from record where date= ′1999/12/01′ (< 1秒)

    你會(huì)發(fā)現(xiàn)SQL明顯快很多

    4、 盡量不要對(duì)建立了索引的字段,作任何的直接處理
    select * from employs where first_name + last_name ='beill cliton';
    無(wú)法使用索引

    改為:
    select * from employee where
    first_name = substr('beill cliton',1,instr('beill cliton',' ')-1)
    and
    last_name = substr('beill cliton',instr('beill cliton',' ')+1)
    則可以使用索引
    5、 不同類型的索引效能是不一樣的,應(yīng)盡可能先使用效能高的
    比如:數(shù)字類型的索引查找效率高于字符串類型,定長(zhǎng)字符串char,nchar的索引效率高于變長(zhǎng)字符串varchar,nvarchar的索引。
    應(yīng)該將
    where username='張三' and age>20
    改進(jìn)為
    where age>20 and username='張三'
    注意:

    此處,SQL的查詢分析優(yōu)化功能可以做到自動(dòng)重排條件順序,但還是建議預(yù)先手工排列好。


    6、 盡量不要使用 is null 與 is not null作為查詢條件
      任何包含null值的列都將不會(huì)被包含在索引中,如果某列數(shù)據(jù)中存在空值,那么對(duì)該列建立索引的性能提升是值得懷疑的,尤其是將null作為查詢條件的一部分時(shí)。建議一方面避免使用is null和is not null, 另一方面不要讓數(shù)據(jù)庫(kù)字段中存在null, 即使沒(méi)有內(nèi)容,也應(yīng)利用缺省值,或者手動(dòng)的填入一個(gè)值,如:’’ 空字符串。

    7、 某些情況下IN 的作用與OR 相當(dāng) ,且都不能充分利用索引
    例:表stuff有200000行,id_no上有非群集索引,請(qǐng)看下面這個(gè)SQL:
    select count(*) from stuff where id_no in(′0′,′1′) (23秒)

    where條件中的′in′在邏輯上相當(dāng)于′or′,所以語(yǔ)法分析器會(huì)將in (′0′,′1′)轉(zhuǎn)化為id_no =′0′ or id_no=′1′來(lái)執(zhí)行。我們期望它會(huì)根據(jù)每個(gè)or子句分別查找,再將結(jié)果相加,這樣可以利用id_no上的索引;但實(shí)際上,它卻采用了"OR策略",即先取出滿足每個(gè)or子句的行,存入臨時(shí)數(shù)據(jù)庫(kù)的工作表中,再建立唯一索引以去掉重復(fù)行,最后從這個(gè)臨時(shí)表中計(jì)算結(jié)果。因此,實(shí)際過(guò)程沒(méi)有利用id_no上索引,并且完成時(shí)間還要受tempdb數(shù)據(jù)庫(kù)性能的影響。
    實(shí)踐證明,表的行數(shù)越多,工作表的性能就越差,當(dāng)stuff有620000行時(shí),執(zhí)行時(shí)間會(huì)非常長(zhǎng)!如果確定不同的條件不會(huì)產(chǎn)生大量重復(fù)值,還不如將or子句分開(kāi):
    select count(*) from stuff where id_no=′0′
    select count(*) from stuff where id_no=′1′
    得到兩個(gè)結(jié)果,再用union作一次加法合算。因?yàn)槊烤涠际褂昧怂饕瑘?zhí)行時(shí)間會(huì)比較短,
    select count(*) from stuff where id_no=′0′
    union
    select count(*) from stuff where id_no=′1′
    從實(shí)踐效果來(lái)看,使用union在通常情況下比用or的效率要高的多,而exist關(guān)鍵字和in關(guān)鍵字在用法上類似,性能上也類似,都會(huì)產(chǎn)生全表掃描,效率比較低下,根據(jù)未經(jīng)驗(yàn)證的說(shuō)法,exist可能比in要快些。

    8、 使用變通的方法提高查詢效率
      like關(guān)鍵字支持通配符匹配,但這種匹配特別耗時(shí)。例如:select * from customer where zipcode like “21_ _ _”,即使在zipcode字段上已建立了索引,在這種情況下也可能還是采用全表掃描方式。如果把語(yǔ)句改為:select * from customer where zipcode >“21000”,在執(zhí)行查詢時(shí)就會(huì)利用索引,大大提高速度。但這種變通是有限制的,不應(yīng)引起業(yè)務(wù)意義上的損失,對(duì)于郵政編碼而言,zipcode like “21_ _ _” 和 zipcode >“21000” 意義是完全一致的。
    9、 組合索引的高效使用
    假設(shè)已在date,place,amount三個(gè)字段上建立了組合索引
    select count(*) from record
    where date > ′19991201′ and date < ′19991214′ and amount > 2000
    (< 1秒)

    select date,sum(amount) from record group by date
    (11秒)

    select count(*) from record
    where date > ′19990901′ and place in (′BJ′,′SH′)
    (< 1秒)
    這是一個(gè)設(shè)置較合理的組合索引。它將date作為前導(dǎo)列,使每個(gè)SQL都可以利用索引,并且在第一和第三個(gè)SQL中形成了索引覆蓋,因而性能達(dá)到了最優(yōu)。如果索引不便于更改,修正SQL中的條件順序以配合索引順序也是可行的。
    10、 order by按聚集索引列排序效率最高
    排序是較耗時(shí)的操作,應(yīng)盡量簡(jiǎn)化或避免對(duì)大型表進(jìn)行排序,如縮小排序的列的范圍,只在有索引的列上排序等等。
    我們來(lái)看:(gid是主鍵,fariqi是聚合索引列)
    select top 10000 gid,fariqi,reader,title from tgongwen
    用時(shí):196 毫秒。 掃描計(jì)數(shù) 1,邏輯讀 289 次,物理讀 1 次,預(yù)讀 1527 次。
    select top 10000 gid,fariqi,reader,title from tgongwen order by gid asc
    用時(shí):4720毫秒。 掃描計(jì)數(shù) 1,邏輯讀 41956 次,物理讀 0 次,預(yù)讀 1287 次。
    select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc
    用時(shí):4736毫秒。 掃描計(jì)數(shù) 1,邏輯讀 55350 次,物理讀 10 次,預(yù)讀 775 次。
    select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi asc
    用時(shí):173毫秒。 掃描計(jì)數(shù) 1,邏輯讀 290 次,物理讀 0 次,預(yù)讀 0 次。
    select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi desc
    用時(shí):156毫秒。 掃描計(jì)數(shù) 1,邏輯讀 289 次,物理讀 0 次,預(yù)讀 0 次。
    從以上我們可以看出,不排序的速度以及邏輯讀次數(shù)都是和“order by 聚集索引列” 的速度是相當(dāng)?shù)模@些都比“order by 非聚集索引列”的查詢速度是快得多的。
    同時(shí),按照某個(gè)字段進(jìn)行排序的時(shí)候,無(wú)論是正序還是倒序,速度是基本相當(dāng)?shù)摹?br />三、 關(guān)于節(jié)省數(shù)據(jù)查詢系統(tǒng)開(kāi)銷方面的措施
    1、 使用TOP盡量減少取出的數(shù)據(jù)量
    TOP是SQL SERVER中用來(lái)提取前幾條或前某個(gè)百分比數(shù)據(jù)的關(guān)鍵詞。
    select top 20 gid,fariqi,reader,title from tgongwen order by gid desc
    select top 60 percent gid,fariqi,reader,title from tgongwen order by gid desc
    在實(shí)際的應(yīng)用中,應(yīng)該經(jīng)常利用top 剔除掉不必要的數(shù)據(jù),只保留必須的數(shù)據(jù)集合。這樣不僅可以減少數(shù)據(jù)庫(kù)邏輯讀的次數(shù),還能避免不必要的內(nèi)存浪費(fèi),對(duì)系統(tǒng)性能的提升都是有好處的。

    2、 字段提取要按照“需多少、提多少”的原則,避免“select *”
    這個(gè)舉個(gè)例子:
    select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc
    用時(shí):4673毫秒
    select top 10000 gid,fariqi,title from tgongwen order by gid desc
    用時(shí):1376毫秒
    select top 10000 gid,fariqi from tgongwen order by gid desc
    用時(shí):80毫秒
    由此看來(lái),字段大小越大,數(shù)目越多,select所耗費(fèi)的資源就越多,比如取int類型的字段就會(huì)比取char的快很多。我們每少提取一個(gè)字段,數(shù)據(jù)的提取速度就會(huì)有相應(yīng)的提升。提升的幅度根據(jù)舍棄的字段的大小來(lái)判斷。
    3、 count(*) 與 count(字段) 方法比較
    我們來(lái)看一些實(shí)驗(yàn)例子(gid為Tgongwen的主鍵):
    select count(*) from Tgongwen
    用時(shí):1500毫秒
    select count(gid) from Tgongwen
    用時(shí):1483毫秒
    select count(fariqi) from Tgongwen
    用時(shí):3140毫秒
    select count(title) from Tgongwen
    用時(shí):52050毫秒
    從以上可以看出,用count(*)和用count(主鍵)的速度是相當(dāng)?shù)模鴆ount(*)卻比其他任何除主鍵以外的字段匯總速度要快,而且字段越長(zhǎng),匯總速度就越慢。如果用count(*), SQL SERVER會(huì)自動(dòng)查找最小字段來(lái)匯總。當(dāng)然,如果您直接寫count(主鍵)將會(huì)來(lái)的更直接些。
    4、 有嵌套查詢時(shí),盡可能在內(nèi)層過(guò)濾掉數(shù)據(jù)
    如果一個(gè)列同時(shí)在主查詢和where子句中出現(xiàn),很可能當(dāng)主查詢中的列值改變之后,子查詢必須重新查詢一次。而且查詢嵌套層次越多,效率越低,因此應(yīng)當(dāng)盡量避免子查詢。如果子查詢不可避免,那么要在子查詢中過(guò)濾掉盡可能多的行。
    5、 多表關(guān)聯(lián)查詢時(shí),需注意表順序,并盡可能早的過(guò)濾掉數(shù)據(jù)
    在使用Join進(jìn)行多表關(guān)聯(lián)查詢時(shí)候,應(yīng)該使用系統(tǒng)開(kāi)銷最小的方案。連接條件要充份考慮帶有索引的表、行數(shù)多的表,并注意優(yōu)化表順序;說(shuō)的簡(jiǎn)單一點(diǎn),就是盡可能早的將之后要做關(guān)聯(lián)的數(shù)據(jù)量降下來(lái)。
    一般情況下,sqlserver 會(huì)對(duì)表的連接作出自動(dòng)優(yōu)化。例如:
    select name,no from A
    join B on A. id=B.id
    join C on C.id=A.id
    where name='wang'
    盡管A表在From中先列出,然后才是B,最后才是C。但sql server可能會(huì)首先使用c表。它的選擇原則是相對(duì)于該查詢限制為單行或少數(shù)幾行,就可以減少在其他表中查找的總數(shù)據(jù)量。絕大多數(shù)情況下,sql server 會(huì)作出最優(yōu)的選擇,但如果你發(fā)覺(jué)某個(gè)復(fù)雜的聯(lián)結(jié)查詢速度比預(yù)計(jì)的要慢,就可以使用SET FORCEPLAN語(yǔ)句強(qiáng)制sql server按照表出現(xiàn)順序使用表。如上例加上:SET FORCEPLAN ON…….SET FORCEPLAN OFF 表的執(zhí)行順序?qū)?huì)按照你所寫的順序執(zhí)行。在查詢分析器中查看2種執(zhí)行效率,從而選擇表的連接順序。SET FORCEPLAN的缺點(diǎn)是只能在存儲(chǔ)過(guò)程中使用。

    小結(jié):
    ? 聚集索引比較寶貴,應(yīng)該用在查詢頻率最高的地方;
    ? 在數(shù)據(jù)為“既不是絕大多數(shù)相同,也不是極少數(shù)相同”狀態(tài)時(shí),
    最能發(fā)揮聚集索引的潛力;
    ? 復(fù)合索引的設(shè)置和使用要注意保持順序一致;
    ? 條件子句的表達(dá)式最好符合SARG規(guī)范,是可利用索引的;
    ? 任何對(duì)列的操作都導(dǎo)致全表掃描,如數(shù)據(jù)庫(kù)函數(shù)、計(jì)算表達(dá)式等,
    查詢時(shí)應(yīng)盡可能將操作移至等號(hào)的某一邊;
    ? 要注意含有null值時(shí),是不能充分利用索引的;
    ? exist, in、or等子句常會(huì)使索引失效;
    如果不產(chǎn)生大量重復(fù)值,可以考慮把子句拆開(kāi),再用union拼合;
    ? 排序時(shí)應(yīng)充分利用帶索引的字段;
    ? 盡可能早,快的過(guò)濾掉無(wú)用的數(shù)據(jù),只將必須的數(shù)據(jù)帶到后續(xù)的操作中去
    從前面講敘的內(nèi)容可以看出,SQL語(yǔ)句優(yōu)化的實(shí)質(zhì)就是在結(jié)果正確的前提下,用分析優(yōu)化器可以識(shí)別的SARG規(guī)范語(yǔ)句,充份利用索引,減少數(shù)據(jù)的I/O次數(shù),盡量避免全表掃描的發(fā)生。
    以上內(nèi)容有些是指導(dǎo)性的理論原則,有些是實(shí)際摸索的經(jīng)驗(yàn),大家在使用時(shí)應(yīng)靈活處理,根據(jù)實(shí)際情況,選擇合適的方法。本文中列舉的實(shí)驗(yàn)數(shù)據(jù)僅作比對(duì)用,不具備普遍意義。大家在實(shí)際項(xiàng)目中,應(yīng)充分利用性能監(jiān)測(cè)和分析工具(如SQLSERVER帶的相關(guān)工具)來(lái)檢驗(yàn)自己的優(yōu)化效果
    此外,還有很重要的一點(diǎn)要提醒大家,同樣復(fù)雜的數(shù)據(jù)操作,在SQLSERVER數(shù)據(jù)庫(kù)級(jí)別完成的代價(jià)要遠(yuǎn)遠(yuǎn)小于在應(yīng)用端用程序代碼完成的代價(jià),所以建議大家全面,深入的學(xué)習(xí)SQL語(yǔ)法中重要關(guān)鍵字的應(yīng)用,如:Group By ,Having等,盡量把數(shù)據(jù)操作任務(wù)放在數(shù)據(jù)庫(kù)系統(tǒng)中完成 。數(shù)據(jù)庫(kù)應(yīng)用系統(tǒng)的性能優(yōu)化是一個(gè)復(fù)雜的過(guò)程,上述這些只是在SQL語(yǔ)句層次的一種體現(xiàn),深入研究還會(huì)涉及數(shù)據(jù)庫(kù)層的資源配置、網(wǎng)絡(luò)層的流量控制以及操作系統(tǒng)層的總體設(shè)計(jì)等等,這些將在以后的文章中詳細(xì)論述

    posted on 2006-12-11 11:49 ASONG 閱讀(298) 評(píng)論(0)  編輯  收藏 所屬分類: database

    主站蜘蛛池模板: 中出五十路免费视频| 国产精品亚洲一区二区三区久久| 日韩精品无码免费视频| 日韩一级在线播放免费观看| 亚洲情A成黄在线观看动漫软件 | 亚洲国产成人手机在线观看| 亚洲人成在线免费观看| 亚洲成a人片在线观看播放| 亚洲视频在线免费播放| 亚洲一区二区三区深夜天堂| 成人免费看片又大又黄| 久久亚洲中文字幕无码| 免费人成年激情视频在线观看 | 免费播放在线日本感人片| 久久亚洲国产伦理| 最刺激黄a大片免费网站| 亚洲女人18毛片水真多| 成人黄18免费视频| 在线观看亚洲电影| 亚洲啪啪综合AV一区| 一级毛片不卡片免费观看| 91亚洲自偷在线观看国产馆| 99热在线精品免费全部my| 狼人大香伊蕉国产WWW亚洲| 亚洲自偷自偷图片| 最近中文字幕完整免费视频ww| 久久精品国产亚洲av麻豆蜜芽| 欧洲精品免费一区二区三区| 一道本在线免费视频| 亚洲国产女人aaa毛片在线 | 亚洲综合激情五月色一区| 国产在线观看www鲁啊鲁免费| XXX2高清在线观看免费视频| 亚洲国产精品久久久久久| 啦啦啦手机完整免费高清观看| 农村寡妇一级毛片免费看视频| 五月天网站亚洲小说| 国产成人精品免费直播| 国产好大好硬好爽免费不卡| 亚洲精品人成网线在线播放va | 亚洲中文字幕无码爆乳app|