久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

數(shù)據(jù)庫JOIN原理

 hh3755 2012-12-20

通往性能優(yōu)化的天堂-地獄 JOIN方法說明


請(qǐng)查看原文: http://www.cnblogs.com/RicCC/archive/2007/06/26/796481.html


下面只做備份:

    前言
    不管是博客園還是CSDN,看到很多朋友對(duì)數(shù)據(jù)庫的理解,、認(rèn)識(shí)還是沒有突破一個(gè)瓶頸,,而這個(gè)瓶頸往往只是一層窗紙,越過了你將看到一個(gè)新世界,。
    04,、05年做項(xiàng)目的時(shí)候,用SQL Server 2000,,核心表(大部分使用頻繁的關(guān)鍵功能每次都要用到)達(dá)到了800萬數(shù)據(jù)量,,很早以前查過一些相關(guān)表,有的達(dá)到了3000多萬,,磁盤使用的光纖盤,,100G空間,每周必須備份轉(zhuǎn)移數(shù)據(jù),,否則100G空間一周會(huì)滿掉,,這個(gè)系統(tǒng)幾年來,目前仍然保持非常良好的性能,。還聽說過朋友的SQL Server 2000數(shù)據(jù)庫工作在幾十TB的環(huán)境下,,高并發(fā)量,對(duì)這種級(jí)別的駕馭能力我還是差的很遙遠(yuǎn),。
    想當(dāng)年,,也是一提SQL Server,就覺得它的性能沒法跟Oracle相比,,一提到大數(shù)據(jù)處理就想到Oracle,。自己一路走來,在本地blog上記錄了很多優(yōu)化方面的post,,對(duì)的錯(cuò)的都有,,沒有時(shí)間系列的整理出來,這篇文章將join方法的概念稍微整理在一起,,給大家個(gè)參考,。通過查資料了解里面提到的各種概念,在實(shí)際中不斷驗(yàn)證總結(jié),,完全可以對(duì)數(shù)據(jù)庫一步步深入理解下去的,。
    我只對(duì)SQL Server 2000比較了解,但這并不阻礙我在Oracle,、MySql進(jìn)行SQL調(diào)優(yōu),、產(chǎn)品架構(gòu),,因?yàn)樵跀?shù)據(jù)庫理論原理上,各大數(shù)據(jù)庫基本出入不大,,對(duì)數(shù)據(jù)庫的深入理解,,也不會(huì)影響你架構(gòu)設(shè)計(jì)思想變壞,相反給你帶來的是更深層次的思考,。
    RicCC:2007.06.26

    關(guān)于執(zhí)行計(jì)劃的說明
    在SQL Server查詢分析器的Query菜單中選擇Show Execution Plan,,運(yùn)行SQL查詢語句,在結(jié)果窗口中有Grid,、Execution Plan,、Messages三個(gè)Tab??磮D形形式的執(zhí)行計(jì)劃,,順序是從右到左,這也是執(zhí)行的順序,。執(zhí)行計(jì)劃中的每一個(gè)圖標(biāo)表示一個(gè)操作,,每一個(gè)操作都會(huì) 有一個(gè)或多個(gè)輸入,也會(huì)有一個(gè)或多個(gè)輸出,。輸入和輸出,,有可能是一個(gè)物理數(shù)據(jù)表、索引數(shù)據(jù)結(jié)構(gòu),,或者是執(zhí)行過程中的一些中間結(jié)果集/數(shù)據(jù)結(jié)構(gòu),。鼠標(biāo)移動(dòng)到 圖標(biāo)上,會(huì)顯示這個(gè)操作的具體信息,,例如邏輯和物理操作名稱,、記錄的數(shù)量和大小、I/O成本,、CPU成本,、操作的具體表達(dá)式(參數(shù)Argument)。鼠 標(biāo)移動(dòng)到連接箭頭上,,會(huì)顯示箭頭起始端的操作輸出結(jié)果集的記錄數(shù),、記錄的大小,一般情況下可以將這個(gè)輸出結(jié)果集理解為箭頭結(jié)束端的輸入,。
    另外關(guān)于執(zhí)行計(jì)劃的一些補(bǔ)充說明:1. 執(zhí)行計(jì)劃中顯示的信息,,都是一個(gè)“評(píng)估”的結(jié)果,不是100%準(zhǔn)確的信息,,例如記錄數(shù)量是取自統(tǒng)計(jì)信息,,I/O成本、CPU成本來自執(zhí)行計(jì)劃生成過程中基 于統(tǒng)計(jì)信息等得出的評(píng)估結(jié)果。2. 執(zhí)行計(jì)劃不一定準(zhǔn)確,,一方面受SQL Server維護(hù)的統(tǒng)計(jì)信息準(zhǔn)確性的影響,,另一方面SQL語句編譯時(shí)刻與執(zhí)行時(shí)刻的環(huán)境(內(nèi)存使用狀況、CPU狀況等)可能會(huì)不一樣,。
    關(guān)于統(tǒng)計(jì)信息、I/O成本和CPU成本的評(píng)估,、SQL語句的編譯和執(zhí)行過程,,這里不再深入。另外盡管執(zhí)行計(jì)劃不一定準(zhǔn)確,,但它仍是SQL語句分析最重要的依據(jù),,因?yàn)槟憧梢岳斫鉃椋^大部分情況下,,SQL Server是以這種方式來執(zhí)行的,。

    JOIN方法說明
    數(shù)據(jù)庫中,象tableA inner join tableB,、tableA left out join tableB這樣的SQL語句是如何執(zhí)行join操作的,?就是說SQL Server使用什么算法實(shí)現(xiàn)兩個(gè)表數(shù)據(jù)的join操作?
    SQL Server 2000有三種方式:nested loop,、merge,、hash。Oracle也是使用這三種方式,,不過Oracle選擇使用nested loop的條件跟SQL Server有點(diǎn)差別,,內(nèi)存管理機(jī)制跟SQL Server不一樣,因此查看執(zhí)行計(jì)劃,,Oracle中nested loop運(yùn)用非常多,,而merge和hash方式相對(duì)較少,SQL Server中,,merge跟hash方式則是非常普遍,。
    以SQL Server 2000為例對(duì)這三種方式進(jìn)行說明,穿插在里面講解執(zhí)行計(jì)劃的一些初級(jí)使用,。

    1. nested loop join
    1.1 示例SQL
    select ... from tableA inner join tableB on tableA.col1=tableB.col1 where tableA.col2=? and tableB.col2=?
    tableA中沒有建立任何索引,,tableB中在col1上有建立一個(gè)主鍵(聚集索引)。
    1.2 算法偽代碼描述
    foreach rowA in tableA where tableA.col2=?
    {
    search rowsB from tableB where tableB.col1=rowA.col1 and tableB.col2=? ;
    if(rowsB.Count<=0)
        discard rowA ;
    else
        output rowA and rowsB ;
    }
    join操作有兩個(gè)輸入,,上面例子中tableA是outer input,,用于外層循環(huán);tableB是inner input,,用于循環(huán)內(nèi)部,。下面針對(duì)執(zhí)行計(jì)劃描述一下SQL Server完成這個(gè)操作的具體步驟。
    1.3 查看執(zhí)行計(jì)劃方法    移到文章最前面,。
    1.4 執(zhí)行步驟
    下面是示例SQL的執(zhí)行計(jì)劃圖,。nested loop操作的右邊,,位于上面的是outer input,位于下面的是inner input,。你不能夠根據(jù)join中哪個(gè)表出現(xiàn)在前面來確定outer input和inner input關(guān)系,,而必須從執(zhí)行計(jì)劃中來確定,因?yàn)镾QL Server會(huì)自動(dòng)選擇哪個(gè)作為inner input,。
    
    a) 對(duì)tableA執(zhí)行Table Scan操作,。這個(gè)操作的輸入是tableA表中的數(shù)據(jù),這些數(shù)據(jù)位于磁盤上,,操作過程中被加載到內(nèi)存,;輸出是符合條件的記錄集,將作為b)的outer input,。在這個(gè)操作中,,tableA.col1=?的條件會(huì)被使用。
    b) 執(zhí)行上面?zhèn)未a描述的nested loop操作,。對(duì)a)中的每個(gè)輸出記錄,,執(zhí)行步驟c)。
    c) 對(duì)tableB執(zhí)行Clustered Index Seek操作,。這個(gè)操作是在nested loop循環(huán)里面執(zhí)行的,,輸入是tableB表的聚集索引數(shù)據(jù)。它使用tableB.col1=rowA.col1和tableB.col2=?這兩個(gè)條件,,從tableB的聚集索引中選擇符合條件的結(jié)果,。
    d) 構(gòu)造返回結(jié)果集。從nested loop的輸出中,,整理出select中指定的字段,,構(gòu)造最終輸出結(jié)果集。
    1.5 進(jìn)階說明
    上面例子對(duì)inner input使用的是聚集索引,,下面看一下非聚集索引的情況,,加強(qiáng)對(duì)執(zhí)行計(jì)劃的理解、分析能力,。
    把tableB col1上的主鍵修改為非聚集方式,,示例的SQL語句執(zhí)行計(jì)劃如下:
    
    前面三個(gè)執(zhí)行步驟a)、b),、c)跟1.4中一樣,,有一點(diǎn)需要注意的是,步驟c)是執(zhí)行Index Seek操作,,它跟Clustered Index Seek有區(qū)別,。聚集索引的根節(jié)點(diǎn)是每一條實(shí)際數(shù)據(jù)記錄,而非聚集索引的根節(jié)點(diǎn)是對(duì)聚集索引根結(jié)點(diǎn)鍵值的引用(如果表存在聚集索引),或者是對(duì)實(shí)際數(shù)據(jù)記錄rowid的引用(指沒有聚集索引的表,,這種表稱為heap表),。Clustered Index Seek執(zhí)行之后,實(shí)際的物理數(shù)據(jù)記錄已經(jīng)被加載到內(nèi)存中,,而Index Seek操作之后,,并沒有加載實(shí)際的物理數(shù)據(jù)記錄,而只是非聚集索引的根結(jié)點(diǎn)數(shù)據(jù),,其中只包含了索引字段數(shù)據(jù)以及引用的聚集索引鍵值或者rowid,。SQL Server在這個(gè)步驟中使用非聚集索引根結(jié)點(diǎn)數(shù)據(jù)中的索引字段值,與outer input中的記錄(rowA)關(guān)聯(lián)字段進(jìn)行匹配,,判斷是否是符合條件的結(jié)果,如果是,,則將非聚集索引根結(jié)點(diǎn)數(shù)據(jù)結(jié)構(gòu)保存到nested loop操作的輸出數(shù)據(jù)結(jié)構(gòu)中,,并且會(huì)創(chuàng)建一個(gè)書簽(Bookmark),指示在必要的時(shí)候需要根據(jù)這個(gè)書簽去獲取引用的數(shù)據(jù),。
    d) 執(zhí)行Bookmark Lookup操作,。nested loop操作的輸出是一個(gè)內(nèi)存數(shù)據(jù)結(jié)構(gòu),在從這個(gè)內(nèi)存數(shù)據(jù)結(jié)構(gòu)中整理出整個(gè)查詢語句的輸出結(jié)果集之前,,需要處理前面的書簽引用問題,,Bookmark Lookup操作就是根據(jù)書簽中引用的聚集索引鍵值或者rowid獲取具體記錄數(shù)據(jù)。
    e) Filter過濾操作,?;仡櫱懊鎺讉€(gè)操作,在執(zhí)行nested loop時(shí)只是使用非聚集索引的索引字段(tableB.col1)跟outer input的關(guān)聯(lián)字段進(jìn)行匹配,,到目前為止還沒有使用tableB.col2=?這個(gè)條件,,這個(gè)操作就是使用tableB.col2=?對(duì)Bookmark Lookup的輸出進(jìn)行過濾。
    看的仔細(xì)的人到這里后可能會(huì)有幾個(gè)疑問,,1. tableA.col2=?怎么沒有一個(gè)Filter操作,?2. 在1.4中為什么沒有出現(xiàn)Filter操作?解釋如下:1. 在tableA上面執(zhí)行的是Table Scan操作,,是直接對(duì)每條實(shí)際數(shù)據(jù)進(jìn)行掃描,,在這個(gè)掃描過程中可以使用tableA.col2=?這個(gè)條件進(jìn)行過濾,避免一個(gè)額外的Filter操作,。鼠標(biāo)移動(dòng)到Table Scan操作上,,從提示信息的參數(shù)(Argument)里面可以看到tableA.col2=?的條件已經(jīng)被運(yùn)用上了。2. 前面說過,,聚集索引的根節(jié)點(diǎn)是實(shí)際數(shù)據(jù)記錄,,執(zhí)行Clustered Index Seek的時(shí)候,最終也是掃描到了實(shí)際數(shù)據(jù)記錄,在這個(gè)過程中運(yùn)用tableB.col2=?這個(gè)條件,,同樣避免一個(gè)額外的Filter操作,。這就是1.4中沒有Filter操作的原因。
    f) 構(gòu)造返回結(jié)果集,。跟1.4步驟d)一樣,。
    1.6 nested loop使用條件
    任何一個(gè)join操作,如果滿足nested loop使用條件,,查詢優(yōu)化過程中SQL Server就會(huì)對(duì)nested loop的成本(I/O成本,、CPU成本等)進(jìn)行評(píng)估,基于評(píng)估結(jié)果確定是否使用這種join方式,。
    使用nested loop方式的條件是:a) outer input的記錄數(shù)不大,,最好是在1000-2000以下,一般超過3000就很難說了,,基本不大會(huì)選擇nested loop,。b) 作為inner input的表中,有可用于這個(gè)查詢的索引,。
    這是因?yàn)閛uter input記錄數(shù)不大,,意味著外層循環(huán)次數(shù)比較小,;inner input上有可用的索引,,意味著在循環(huán)里面搜索inner input表中是否存在匹配的記錄時(shí),效率會(huì)很高,,哪怕inner input表實(shí)際記錄數(shù)有幾百萬,。基于這兩個(gè)條件,,nested loop的執(zhí)行效率非常高,,在三種join方式里面,是內(nèi)存和CPU消耗最少的一種(不合理的強(qiáng)制指定nested loop方式除外),。
    關(guān)于使用條件另外的說明:outer input的記錄數(shù),,并不是指outer input表中實(shí)際記錄數(shù),例如示例SQL中,,如果tableA在col2上有維護(hù)統(tǒng)計(jì)信息(存在col2的索引或者是單獨(dú)維護(hù)的統(tǒng)計(jì)信息),,并且tableA.col2=?的條件值符合SARG(可搜索參數(shù))形式,那么查詢編譯時(shí)刻SQL Server就能夠利用統(tǒng)計(jì)信息和條件值評(píng)估出符合條件的記錄數(shù),,查詢執(zhí)行時(shí)刻符合條件tableA.col2=?的記錄才被用于外層循環(huán),。inner input表中有可用的索引,是指inner input表中用于和outer input表關(guān)聯(lián)的字段(一個(gè)或多個(gè)字段)能夠命中某個(gè)索引(這些字段的部分或者全部出現(xiàn)在某個(gè)索引字段的前面),。
    符合上面的條件,,也不是說SQL Server 100%就會(huì)選擇nested loop,。因?yàn)镾QL Server的查詢優(yōu)化器是基于成本評(píng)估的,如果其它方案評(píng)估出的成本勝過這個(gè),,SQL Server會(huì)選擇其它的join方式,。舉個(gè)例子,如果inner input上符合條件的索引是非聚集索引,,這樣SQL Server可能需要一個(gè)額外的Bookmark Lookup操作獲取實(shí)際記錄數(shù)據(jù),,如果inner input表數(shù)據(jù)量非常大,索引碎片程度很高等情況,,可能導(dǎo)致Bookmark Lookup成本非常高,,SQL Server會(huì)嘗試其它join方案的評(píng)估選擇。
    1.7 強(qiáng)制指定nested loop方式
    使用loop關(guān)鍵字實(shí)現(xiàn),,例如tableA inner loop join tableB,,將強(qiáng)制SQL Server使用nested loop方式執(zhí)行這個(gè)join操作?;蛘呤褂胦ption選項(xiàng),,例如tableA inner join tableB option(loop join)
    nested loop算法有它適用的范圍,在這個(gè)范圍之內(nèi)效率是最高的,,超出這個(gè)范圍效率反而很差,,除非你有十分的把握,,不要隨意強(qiáng)制指定join方式,。

    接下來就不再象上面這樣詳細(xì)的講述了。
    2. merge join
    merge join第一個(gè)步驟是確保兩個(gè)關(guān)聯(lián)表都是按照關(guān)聯(lián)的字段進(jìn)行排序,。如果關(guān)聯(lián)字段有可用的索引,,并且排序一致,則可以直接進(jìn)行merge join操作,;否則,,SQL Server需要先對(duì)關(guān)聯(lián)的表按照關(guān)聯(lián)字段進(jìn)行一次排序(就是說在merge join前的兩個(gè)輸入上,可能都需要執(zhí)行一個(gè)Sort操作,,再進(jìn)行merge join),。
    兩個(gè)表都按照關(guān)聯(lián)字段排序好之后,merge join操作從每個(gè)表取一條記錄開始匹配,,如果符合關(guān)聯(lián)條件,,則放入結(jié)果集中;否則,,將關(guān)聯(lián)字段值較小的記錄拋棄,,從這條記錄對(duì)應(yīng)的表中取下一條記錄繼續(xù)進(jìn)行匹配,直到整個(gè)循環(huán)結(jié)束,。 
    在多對(duì)多的關(guān)聯(lián)表上執(zhí)行merge join時(shí),,通常需要使用臨時(shí)表進(jìn)行操作,。例如A join B使用merge join時(shí),如果對(duì)于關(guān)聯(lián)字段的某一組值,,在A和B中都存在多條記錄A1,、A2...An、B1,、B2...Bn,,則為A中每一條記錄A1、A2...An,,都必須在B中對(duì)所有相等的記錄B1,、B2...Bn進(jìn)行一次匹配。這樣,,指針需要多次從B1移動(dòng)到 Bn,,每一次都需要讀取相應(yīng)的B1...Bn記錄。將B1...Bn的記錄預(yù)先讀出來放入內(nèi)存臨時(shí)表中,,比從原數(shù)據(jù)頁或磁盤讀取要快,。
    merge join操作本身是非常快的,,但是merge join前進(jìn)行的排序可能會(huì)相當(dāng)耗時(shí)(SQL Server最消耗內(nèi)存和CPU的操作,,一個(gè)是大數(shù)據(jù)排序,一個(gè)是大數(shù)據(jù)的hash運(yùn)算,,這都是指查詢計(jì)劃里面的Sort以及Hash相關(guān)的操作,,例如hash join、使用hash算法實(shí)現(xiàn)的Distinct操作等,,而不是指你的SQL中order by關(guān)鍵字),,尤其是對(duì)數(shù)據(jù)量非常大的記錄集,因此導(dǎo)致使用merge join的查詢成本變得非常高,。對(duì)于數(shù)據(jù)量非常大的表,,如果merge join的關(guān)聯(lián)字段可以使用聚集索引,merge join是最快的Join方法之一,。因此優(yōu)化方案是在表結(jié)構(gòu)設(shè)計(jì)層面良好的設(shè)計(jì)關(guān)聯(lián)關(guān)系和表的索引結(jié)構(gòu),,SQL語句充分利用索引,盡可能減少merge join前的排序操作,,減少Bookmark Lookup操作,。
    一般情況下,如果無法滿足nested loop條件,,會(huì)考慮對(duì)merge join方法的評(píng)估,。merge join的選擇,主要是考慮兩個(gè)輸入的數(shù)據(jù)量,,以及分別對(duì)應(yīng)于關(guān)聯(lián)字段是否能夠命中索引,。例如tableA join tableB,,關(guān)聯(lián)字段在兩個(gè)表中都能命中索引,數(shù)據(jù)量超過了nested loop的選擇范圍,,則會(huì)考慮使用merge join方法,。當(dāng)然,如果tableA和tableB的數(shù)據(jù)量過大導(dǎo)致評(píng)估出來的成本過高,,則會(huì)放棄merge join而評(píng)估hash join了,。
    使用inner merge join或者option(merge join)強(qiáng)制使用merge join方法。

    3. hash join
    hash join有兩個(gè)輸入:build input(也叫做outer input)和probe input(也叫做inner input),,不僅用于inner/left/right join等,,象union/group by等也會(huì)使用hash join進(jìn)行操作,在group by中build input和probe input都是同一個(gè)記錄集,。
    同nested loop,,在執(zhí)行計(jì)劃中build input位于上方,probe input位于下方,。
    hash join操作分兩個(gè)階段完成:build(構(gòu)造)階段和probe(探測(cè))階段,。
    Build階段
    這個(gè)階段主要構(gòu)造hash table。在inner/left/right join等操作中,,表的關(guān)聯(lián)字段作為hash key,;在group by操作中,group by的字段作為hash key,;在union或其它一些去除重復(fù)記錄的操作中,,hash key包括所有的select字段。
    Build操作從build input輸入中取出每一行記錄,,將該行記錄關(guān)聯(lián)字段的值使用hash函數(shù)生成hash值,,這個(gè)hash值對(duì)應(yīng)到hash table中的hash buckets(哈希表目),。如果一個(gè)hash值對(duì)應(yīng)到多個(gè)hash buckts,,則這些hash buckets使用鏈表數(shù)據(jù)結(jié)構(gòu)連接起來。當(dāng)整個(gè)build input的table處理完畢后,,build input中的所有記錄都被hash table中的hash buckets引用/關(guān)聯(lián)了,。
    Probe階段
    在這個(gè)階段,SQL Server從probe input輸入中取出每一行記錄,,同樣將該行記錄關(guān)聯(lián)字段的值,,使用build階段中相同的hash函數(shù)生成hash值,根據(jù)這個(gè)hash值,,從build階段構(gòu)造的hash table中搜索對(duì)應(yīng)的hash bucket,。hash算法中為了解決沖突,hash bucket可能會(huì)鏈接到其它的hash bucket,,probe動(dòng)作會(huì)搜索整個(gè)沖突鏈上的hash bucket,,以查找匹配的記錄,。 
    關(guān)于hash算法的細(xì)節(jié),可以查看數(shù)據(jù)結(jié)構(gòu)的一些資料,。hash算法主要是用于大數(shù)據(jù)量的搜索,,為了避免每次都象merge join一樣在全部的數(shù)據(jù)中進(jìn)行搜索匹配,通過合適的 hash函數(shù),,先給要搜索的數(shù)據(jù)根據(jù)hash key建立hash值作為索引,,在搜索時(shí),先通過hash值定位到一個(gè)較小的搜索范圍,,然后在這個(gè)范圍中搜索匹配符合條件的結(jié)果,,以提高效率。 
    SQL Server將數(shù)據(jù)量較小的表作為build input,,盡量使根據(jù)build input構(gòu)造的hash table能夠完全放在內(nèi)存中,,這樣probe階段的匹配操作就完全是在內(nèi)存中進(jìn)行,這樣的hash join叫做In-Memory Hash Join,。
    如果build input記錄數(shù)非常大,,構(gòu)建的hash table無法在內(nèi)存中容納時(shí),SQL Server分別將build input和probe input切分成多個(gè)分區(qū)部分(partition),,每個(gè)partition都包括一個(gè)獨(dú)立的,、成對(duì)匹配的build input和probe input,這樣就將一個(gè)大的hash join切分成多個(gè)獨(dú)立,、互相不影響的hash join,,每一個(gè)分區(qū)的hash join都能夠在內(nèi)存中完成。SQL Server將切分后的partition文件保存在磁盤上,,每次裝載一個(gè)分區(qū)的build input和probe input到內(nèi)存中,,進(jìn)行一次hash join。這種hash join叫做Grace Hash Join,,使用的Grace Hash Join算法,。
    伴隨著大數(shù)據(jù)的hash join運(yùn)算,還會(huì)有standard external merge sorts,、multiple merge levels,、multiple partitioning steps、multiple partitioning levels,,SQL Server還可能會(huì)使用Recursive Hash Join等算法或其它的優(yōu)化手段,。
    hash join一般都用于大數(shù)據(jù)量的操作,例如join中某個(gè)表的數(shù)據(jù)達(dá)到一定程度或者無法一次加載到內(nèi)存,,另外如果你的關(guān)聯(lián)字段在兩個(gè)join表中都不能夠命中索引,,也是使用hash join來處理。因此一般情況下,,hahs join處理代價(jià)非常高,,是數(shù)據(jù)庫服務(wù)器內(nèi)存和CPU的頭號(hào)殺手之一,,尤其是涉及到分區(qū)(數(shù)據(jù)量太大導(dǎo)致內(nèi)存不夠的情況,或者并發(fā)訪問很高導(dǎo)致當(dāng)前處理線程無法獲得足夠的內(nèi)存,,那么數(shù)據(jù)量不是特大的情況下也可能需要進(jìn)行分區(qū)),,為了盡快的完成所有的分區(qū)步驟,將使用大量異步的I/O操作,,因此期間單一一個(gè)線程就可能導(dǎo)致多個(gè)磁盤驅(qū)動(dòng)器出于忙碌狀態(tài),,這很有可能阻塞其它線程的執(zhí)行。
    使用inner hash join或者option (hash join)強(qiáng)制使用hash join方法,。

    建議
    三種join方法,,都是擁有兩個(gè)輸入。優(yōu)化的基本原則:1. 避免大數(shù)據(jù)的hash join,,盡量將其轉(zhuǎn)化為高效的merge join,、nested loop join??赡苁褂玫氖侄斡斜斫Y(jié)構(gòu)設(shè)計(jì),、索引調(diào)整設(shè)計(jì)、SQL優(yōu)化,,以及業(yè)務(wù)設(shè)計(jì)優(yōu)化,。例如冗余字段的運(yùn)用,將統(tǒng)計(jì)分析結(jié)果用service定期跑到靜態(tài)表中,,適當(dāng)?shù)娜哂啾?,使用AOP或類似機(jī)制同步更新等。2. 盡量減少join兩個(gè)輸入端的數(shù)據(jù)量,。這一點(diǎn)比較常犯的毛病是,,條件不符合SARG(光這一點(diǎn)就有很多高超的技巧可以發(fā)揮),在子查詢內(nèi)部條件給的不充分(SQL過于復(fù)雜情況下SQL Server查詢優(yōu)化器經(jīng)常犯傻,,寫在子查詢外部的條件不會(huì)被用在子查詢內(nèi)部,,影響子查詢內(nèi)部的效率或者是跟子查詢?cè)賘oin時(shí)候的效率)。另外也是設(shè)計(jì),、業(yè)務(wù)端盡量限制這兩個(gè)輸入的數(shù)據(jù)量了,。
    關(guān)于業(yè)務(wù)設(shè)計(jì)方面的優(yōu)化,,參考以前寫的一篇post:系統(tǒng)分析設(shè)計(jì) 一個(gè)JOIN問題解決方案的感想 重視業(yè)務(wù)分析設(shè)計(jì),。

    補(bǔ)充(2007.06.27):關(guān)于SQL Server 2005
    大致看了下SQL Server 2005,執(zhí)行計(jì)劃的顯示確實(shí)有一些不一樣,,但主要部分或者說原理上是差不多的,,不會(huì)有多少偏差。上面的示例SQL,,在tableB上面使用非聚集索引時(shí),,SQL Server 2005的執(zhí)行計(jì)劃圖如下:
    
    一個(gè)主要的不同點(diǎn)是SQL Server 2000下面Bookmark Lookup操作,,在2005下面顯示成一個(gè)RID Lookup操作 + 一個(gè)Nested Loops操作實(shí)現(xiàn),其實(shí)這也是很好理解的,,可以說這樣顯示執(zhí)行計(jì)劃更合理一點(diǎn),,讓你一看到這個(gè)操作,就知道它是通過一個(gè)循環(huán)機(jī)制到tableB中獲取實(shí)際數(shù)據(jù),。
    另外一點(diǎn)是,,將鼠標(biāo)移動(dòng)到執(zhí)行計(jì)劃的圖標(biāo)上面后,彈出的提示信息的一些改變,,例如2005里面會(huì)顯示每個(gè)操作的輸出列表(output list),,而我上面的文章中基本都使用“輸出數(shù)據(jù)結(jié)構(gòu)”這樣一個(gè)詞匯在表達(dá)。通過查看output list,,你更能明白R(shí)ID Lookup(Bookmark Lookup)這樣的操作存在的理由了,。
    最后,2005里面可以將圖形顯示的執(zhí)行計(jì)劃保存下來,,以后可以打開再以圖形方式進(jìn)行查看分析,,這個(gè)在2000下面是不行的,2000只能保存執(zhí)行計(jì)劃的文本,。這樣一些小功能對(duì)于分析SQL性能非常有用,,在圖形界面上的分析更直觀。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多