版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
大數(shù)據(jù)量高并發(fā)的數(shù)據(jù)庫優(yōu)化一、數(shù)據(jù)庫構(gòu)造的設(shè)計(jì)如果不能設(shè)計(jì)一種合理的數(shù)據(jù)庫模型,不僅會(huì)增加客戶端和服務(wù)器段程序的編程和維護(hù)的難度,并且將會(huì)影響系統(tǒng)實(shí)際運(yùn)行的性能。因此,在一種系統(tǒng)開始實(shí)施之前,完備的數(shù)據(jù)庫模型的設(shè)計(jì)是必須的。在一種系統(tǒng)分析、設(shè)計(jì)階段,由于數(shù)據(jù)量較小,負(fù)荷較低。我們往往只注意到功效的實(shí)現(xiàn),而很難注意到性能的單薄之處,等到系統(tǒng)投入實(shí)際運(yùn)行一段時(shí)間后,才發(fā)現(xiàn)系統(tǒng)的性能在減少,這時(shí)再來考慮提高系統(tǒng)性能則要耗費(fèi)更多的人力物力,而整個(gè)系統(tǒng)也不可避免的形成了一種打補(bǔ)丁工程。因此在考慮整個(gè)系統(tǒng)的流程的時(shí)候,我們必須要考慮,在高并發(fā)大數(shù)據(jù)量的訪問狀況下,我們的系統(tǒng)會(huì)不會(huì)出現(xiàn)極端的狀況。(例如:對(duì)外統(tǒng)計(jì)系統(tǒng)在7月16日出現(xiàn)的數(shù)據(jù)異常的狀況,并發(fā)大數(shù)據(jù)量的的訪問造成,數(shù)據(jù)庫的響應(yīng)時(shí)間不能跟上數(shù)據(jù)刷新的速度造成。具體狀況是:在日期臨界時(shí)(00:00:00),判斷數(shù)據(jù)庫中與否有現(xiàn)在日期的統(tǒng)計(jì),沒有則插入一條現(xiàn)在日期的統(tǒng)計(jì)。在低并發(fā)訪問的狀況下,不會(huì)發(fā)生問題,但是當(dāng)天期臨界時(shí)的訪問量相稱大的時(shí)候,在做這一判斷的時(shí)候,會(huì)出現(xiàn)多次條件成立,則數(shù)據(jù)庫里會(huì)被插入多條現(xiàn)在日期的統(tǒng)計(jì),從而造成數(shù)據(jù)錯(cuò)誤。),數(shù)據(jù)庫的模型擬定下來之后,我們有必要做一種系統(tǒng)內(nèi)數(shù)據(jù)流向圖,分析可能出現(xiàn)的瓶頸。為了確保數(shù)據(jù)庫的一致性和完整性,在邏輯設(shè)計(jì)的時(shí)候往往會(huì)設(shè)計(jì)過多的表間關(guān)聯(lián),盡量的減少數(shù)據(jù)的冗余。(例如顧客表的地區(qū),我們能夠把地區(qū)另外寄存到一種地區(qū)表中)如果數(shù)據(jù)冗余低,數(shù)據(jù)的完整性容易得到確保,提高了數(shù)據(jù)吞吐速度,確保了數(shù)據(jù)的完整性,清晰地體現(xiàn)數(shù)據(jù)元素之間的關(guān)系。而對(duì)于多表之間的關(guān)聯(lián)查詢(特別是大數(shù)據(jù)表)時(shí),其性能將會(huì)減少,同時(shí)也提高了客戶端程序的編程難度,因此,物理設(shè)計(jì)需折衷考慮,根據(jù)業(yè)務(wù)規(guī)則,擬定對(duì)關(guān)聯(lián)表的數(shù)據(jù)量大小、數(shù)據(jù)項(xiàng)的訪問頻度,對(duì)這類數(shù)據(jù)表頻繁的關(guān)聯(lián)查詢應(yīng)適宜提高數(shù)據(jù)冗余設(shè)計(jì)但增加了表間連接查詢的操作,也使得程序的變得復(fù)雜,為了提高系統(tǒng)的響應(yīng)時(shí)間,合理的數(shù)據(jù)冗余也是必要的。設(shè)計(jì)人員在設(shè)計(jì)階段應(yīng)根據(jù)系統(tǒng)操作的類型、頻度加以均衡考慮。另外,最佳不要用自增屬性字段作為主鍵與子表關(guān)聯(lián)。不便于系統(tǒng)的遷移和數(shù)據(jù)恢復(fù)。對(duì)外統(tǒng)計(jì)系統(tǒng)映射關(guān)系丟失(******************)。原來的表格必須能夠通過由它分離出去的表格重新構(gòu)建。使用這個(gè)規(guī)定的好處是,你能夠確保不會(huì)在分離的表格中引入多出的列,全部你創(chuàng)立的表格構(gòu)造都與它們的實(shí)際需要同樣大。應(yīng)用這條規(guī)定是一種好習(xí)慣,但是除非你要解決一種非常大型的數(shù)據(jù),否則你將不需要用到它。(例如一種通行證系統(tǒng),我能夠?qū)SERID,USERNAME,USERPASSWORD,單獨(dú)出來作個(gè)表,再把USERID作為其它表的外鍵)表的設(shè)計(jì)具體注意的問題:1、數(shù)據(jù)行的長度不要超出8020字節(jié),如果超出這個(gè)長度的話在物理頁中這條數(shù)據(jù)會(huì)占用兩行從而造成存儲(chǔ)碎片,減少查詢效率。2、能夠用數(shù)字類型的字段盡量選擇數(shù)字類型而不用字符串類型的(電話號(hào)碼),這會(huì)減少查詢和連接的性能,并會(huì)增加存儲(chǔ)開銷。這是由于引擎在解決查詢和連接回逐個(gè)比較字符串中每一種字符,而對(duì)于數(shù)字型而言只需要比較一次就夠了。3、對(duì)于不可變字符類型char和可變字符類型varchar都是8000字節(jié)char查詢快,但是耗存儲(chǔ)空間,varchar查詢相對(duì)慢某些但是節(jié)省存儲(chǔ)空間。在設(shè)計(jì)字段的時(shí)候能夠靈活選擇,例如顧客名、密碼等長度變化不大的字段能夠選擇CHAR,對(duì)于評(píng)論等長度變化大的字段能夠選擇VARCHAR。4、字段的長度在最大程度的滿足可能的需要的前提下,應(yīng)當(dāng)盡量的設(shè)得短某些,這樣能夠提高查詢的效率,并且在建立索引的時(shí)候也能夠減少資源的消耗。二、查詢的優(yōu)化確保在實(shí)現(xiàn)功效的基礎(chǔ)上,盡量減少對(duì)數(shù)據(jù)庫的訪問次數(shù);通過搜索參數(shù),盡量減少對(duì)表的訪問行數(shù)最小化成果集,從而減輕網(wǎng)絡(luò)負(fù)擔(dān);能夠分開的操作盡量分開解決,提高每次的響應(yīng)速度;在數(shù)據(jù)窗口使用SQL時(shí),盡量把使用的索引放在選擇的首列;算法的構(gòu)造盡量簡樸;在查詢時(shí),不要過多地使用通配符如SELECT*FROMT1語句,要用到幾列就選擇幾列如:SELECTCOL1COL2FROMT1;在可能的狀況下盡量限制盡量成果集行數(shù)如:SELECTTOP300COL1COL2COL3FROMT1由于某些狀況下顧客是不需要那么多的數(shù)據(jù)的。在沒有建索引的狀況下,數(shù)據(jù)庫查找某一條數(shù)據(jù),就必須進(jìn)行全表掃描了,對(duì)全部數(shù)據(jù)進(jìn)行一次遍歷,查找出符合條件的統(tǒng)計(jì)。在數(shù)據(jù)量比較小的狀況下,可能看不出明顯的差別,但是當(dāng)數(shù)據(jù)量大的狀況下,這種狀況就是極為糟糕的了。SQL語句在SQLSERVER中是如何執(zhí)行的,他們緊張自己所寫的SQL語句會(huì)被SQLSERVER誤解。例如:select*fromtable1wherename='zhangsan'andtID>10000和執(zhí)行:select*fromtable1wheretID>10000andname='zhangsan'某些人不懂得以上兩條語句的執(zhí)行效率與否同樣,由于如果簡樸的從語句先后上看,這兩個(gè)語句確實(shí)是不同,如果tID是一種聚合索引,那么后一句僅僅從表的10000條后來的統(tǒng)計(jì)中查找就行了;而前一句則要先從全表中查找看有幾個(gè)name='zhangsan'的,而后再根據(jù)限制條件條件tID>10000來提出查詢成果。事實(shí)上,這樣的緊張是不必要的。SQLSERVER中有一種“查詢分析優(yōu)化器”,它能夠計(jì)算出where子句中的搜索條件并擬定哪個(gè)索引能縮小表掃描的搜索空間,也就是說,它能實(shí)現(xiàn)自動(dòng)優(yōu)化。即使查詢優(yōu)化器能夠根據(jù)where子句自動(dòng)的進(jìn)行查詢優(yōu)化,但有時(shí)查詢優(yōu)化器就會(huì)不按照您的本意進(jìn)行快速查詢。在查詢分析階段,查詢優(yōu)化器查看查詢的每個(gè)階段并決定限制需要掃描的數(shù)據(jù)量與否有用。如果一種階段能夠被用作一種掃描參數(shù)(SARG),那么就稱之為可優(yōu)化的,并且能夠運(yùn)用索引快速獲得所需數(shù)據(jù)。SARG的定義:用于限制搜索的一種操作,由于它普通是指一種特定的匹配,一種值的范疇內(nèi)的匹配或者兩個(gè)以上條件的AND連接。形式以下:列名操作符<常數(shù)或變量>或<常數(shù)或變量>操作符列名列名能夠出現(xiàn)在操作符的一邊,而常數(shù)或變量出現(xiàn)在操作符的另一邊。如:Name=’張三’價(jià)格>50005000<價(jià)格Name=’張三’and價(jià)格>5000如果一種體現(xiàn)式不能滿足SARG的形式,那它就無法限制搜索的范疇了,也就是SQLSERVER必須對(duì)每一行都判斷它與否滿足WHERE子句中的全部條件。因此一種索引對(duì)于不滿足SARG形式的體現(xiàn)式來說是無用的。因此,優(yōu)化查詢最重要的就是,盡量使語句符合查詢優(yōu)化器的規(guī)則避免全表掃描而使用索引查詢。具體要注意的:1.應(yīng)盡量避免在where子句中對(duì)字段進(jìn)行null值判斷,否則將造成引擎放棄使用索引而進(jìn)行全表掃描,如:selectidfromtwherenumisnull能夠在num上設(shè)立默認(rèn)值0,確保表中num列沒有null值,然后這樣查詢:selectidfromtwherenum=02.應(yīng)盡量避免在where子句中使用!=或<>操作符,否則將引擎放棄使用索引而進(jìn)行全表掃描。優(yōu)化器將無法通過索引來擬定將要命中的行數(shù)因此需要搜索該表的全部行。3.應(yīng)盡量避免在where子句中使用or來連接條件,否則將造成引擎放棄使用索引而進(jìn)行全表掃描,如:selectidfromtwherenum=10ornum=20能夠這樣查詢:selectidfromtwherenum=10unionallselectidfromtwherenum=204.in和notin也要慎用,由于IN會(huì)使系統(tǒng)無法使用索引而只能直接搜索表中的數(shù)據(jù)。如:selectidfromtwherenumin(123)對(duì)于持續(xù)的數(shù)值,能用between就不要用in了:selectidfromtwherenumbetween1and35.盡量避免在索引過的字符數(shù)據(jù)中,使用非打頭字母搜索。這也使得引擎無法運(yùn)用索引。見以下例子:SELECT*FROMT1WHERENAMELIKE‘%L%’SELECT*FROMT1WHERESUBSTING(NAME21)=’L’SELECT*FROMT1WHERENAMELIKE‘L%’即使NAME字段建有索引,前兩個(gè)查詢?nèi)匀粺o法運(yùn)用索引完畢加緊操作,引擎不得不對(duì)全表全部數(shù)據(jù)逐條操作來完畢任務(wù)。而第三個(gè)查詢能夠使用索引來加緊操作。6.必要時(shí)強(qiáng)制查詢優(yōu)化器使用某個(gè)索引,如在where子句中使用參數(shù),也會(huì)造成全表掃描。由于SQL只有在運(yùn)行時(shí)才會(huì)解析局部變量,但優(yōu)化程序不能將訪問計(jì)劃的選擇推遲到運(yùn)行時(shí);它必須在編譯時(shí)進(jìn)行選擇。然而,如果在編譯時(shí)建立訪問計(jì)劃,變量的值還是未知的,因而無法作為索引選擇的輸入項(xiàng)。以下面語句將進(jìn)行全表掃描:selectidfromtwherenum=@num能夠改為強(qiáng)制查詢使用索引:selectidfromtwith(index(索引名))wherenum=@num7.應(yīng)盡量避免在where子句中對(duì)字段進(jìn)行體現(xiàn)式操作,這將造成引擎放棄使用索引而進(jìn)行全表掃描。如:SELECT*FROMT1WHEREF1/2=100應(yīng)改為:SELECT*FROMT1WHEREF1=100*2SELECT*FROMRECORDWHERESUBSTRING(CARD_NO14)=’5378’應(yīng)改為:SELECT*FROMRECORDWHERECARD_NOLIKE‘5378%’SELECTmember_numberfirst_namelast_nameFROMmembersWHEREDATEDIFF(yydatofbirthGETDATE())>21應(yīng)改為:SELECTmember_numberfirst_namelast_nameFROMmembersWHEREdateofbirth<DATEADD(yy-21GETDATE())即:任何對(duì)列的操作都將造成表掃描,它涉及數(shù)據(jù)庫函數(shù)、計(jì)算體現(xiàn)式等等,查詢時(shí)要盡量將操作移至等號(hào)右邊。8.應(yīng)盡量避免在where子句中對(duì)字段進(jìn)行函數(shù)操作,這將造成引擎放棄使用索引而進(jìn)行全表掃描。如:selectidfromtwheresubstring(name13)='abc'--name以abc開頭的idselectidfromtwheredatediff(daycreatedate'-11-30')=0--‘-11-30’生成的id應(yīng)改為:selectidfromtwherenamelike'abc%'selectidfromtwherecreatedate>='-11-30'andcreatedate<'-12-1'9.不要在where子句中的“=”左邊進(jìn)行函數(shù)、算術(shù)運(yùn)算或其它體現(xiàn)式運(yùn)算,否則系統(tǒng)將可能無法對(duì)的使用索引。10.在使用索引字段作為條件時(shí),如果該索引是復(fù)合索引,那么必須使用到該索引中的第一種字段作為條件時(shí)才干確保系統(tǒng)使用該索引,否則該索引將不會(huì)被使用,并且應(yīng)盡量的讓字段次序與索引次序相一致。11.諸多時(shí)候用exists是一種好的選擇:selectnumfromawherenumin(selectnumfromb)用下面的語句替代:selectnumfromawhereexists(select1frombwherenum=a.num)SELECTSUM(T1.C1)FROMT1WHERE((SELECTCOUNT(*)FROMT2WHERET2.C2=T1.C2>0)SELECTSUM(T1.C1)FROMT1WHEREEXISTS(SELECT*FROMT2WHERET2.C2=T1.C2)兩者產(chǎn)生相似的成果,但是后者的效率顯然要高于前者。由于后者不會(huì)產(chǎn)生大量鎖定的表掃描或是索引掃描。如果你想校驗(yàn)表里與否存在某條紀(jì)錄,不要用count(*)那樣效率很低,并且浪費(fèi)服務(wù)器資源。能夠用EXISTS替代。如:IF(SELECTCOUNT(*)FROMtable_nameWHEREcolumn_name='xxx')能夠?qū)懗桑篒FEXISTS(SELECT*FROMtable_nameWHEREcolumn_name='xxx')經(jīng)常需要寫一種T_SQL語句比較一種父成果集和子成果集,從而找到與否存在在父成果集中有而在子成果集中沒有的統(tǒng)計(jì),如:SELECTa.hdr_keyFROMhdr_tbla----tbla表達(dá)tbl用別名a替代WHERENOTEXISTS(SELECT*FROMdtl_tblbWHEREa.hdr_key=b.hdr_key)SELECTa.hdr_keyFROMhdr_tblaLEFTJOINdtl_tblbONa.hdr_key=b.hdr_keyWHEREb.hdr_keyISNULLSELECThdr_keyFROMhdr_tblWHEREhdr_keyNOTIN(SELECThdr_keyFROMdtl_tbl)三種寫法都能夠得到同樣對(duì)的的成果,但是效率依次減少。12.盡量使用表變量來替代臨時(shí)表。如果表變量包含大量數(shù)據(jù),請(qǐng)注意索引非常有限(只有主鍵索引)。13.避免頻繁創(chuàng)立和刪除臨時(shí)表,以減少系統(tǒng)表資源的消耗。14.臨時(shí)表并不是不可使用,適宜地使用它們能夠使某些例程更有效,例如,當(dāng)需要重復(fù)引用大型表或慣用表中的某個(gè)數(shù)據(jù)集時(shí)。但是,對(duì)于一次性事件,最佳使用導(dǎo)出表。15.在新建臨時(shí)表時(shí),如果一次性插入數(shù)據(jù)量很大,那么能夠使用selectinto替代createtable,避免造成大量log,以提高速度;如果數(shù)據(jù)量不大,為了緩和系統(tǒng)表的資源,應(yīng)先createtable,然后insert。16.如果使用到了臨時(shí)表,在存儲(chǔ)過程的最后務(wù)必將全部的臨時(shí)表顯式刪除,先truncatetable,然后droptable,這樣能夠避免系統(tǒng)表的較長時(shí)間鎖定。17.在全部的存儲(chǔ)過程和觸發(fā)器的開始處設(shè)立SETNOCOUNTON,在結(jié)束時(shí)設(shè)立SETNOCOUNTOFF。無需在執(zhí)行存儲(chǔ)過程和觸發(fā)器的每個(gè)語句后向客戶端發(fā)送DONE_IN_PROC消息。18.盡量避免大事務(wù)操作,提高系統(tǒng)并發(fā)能力。19.盡量避免向客戶端返回大數(shù)據(jù)量,若數(shù)據(jù)量過大,應(yīng)當(dāng)考慮對(duì)應(yīng)需求與否合理。20.避免使用不兼容的數(shù)據(jù)類型。例如float和int、char和varchar、binary和varbinary是不兼容的。數(shù)據(jù)類型的不兼容可能使優(yōu)化器無法執(zhí)行某些原來能夠進(jìn)行的優(yōu)化操作。例如:SELECTnameFROMemployeeWHEREsalary>60000在這條語句中如salary字段是money型的則優(yōu)化器很難對(duì)其進(jìn)行優(yōu)化由于60000是個(gè)整型數(shù)。我們應(yīng)當(dāng)在編程時(shí)將整型轉(zhuǎn)化成為錢幣型而不要等到運(yùn)行時(shí)轉(zhuǎn)化。21.充足運(yùn)用連接條件,在某種狀況下,兩個(gè)表之間可能不只一種的連接條件,這時(shí)在WHERE子句中將連接條件完整的寫上,有可能大大提高查詢速度。例:SELECTSUM(A.AMOUNT)FROMACCOUNTACARDBWHEREA.CARD_NO=B.CARD_NOSELECTSUM(A.AMOUNT)FROMACCOUNTACARDBWHEREA.CARD_NO=B.CARD_NOANDA.ACCOUNT_NO=B.ACCOUNT_NO第二句將比第一句執(zhí)行快得多。22、使用視圖加速查詢把表的一種子集進(jìn)行排序并創(chuàng)立視圖,有時(shí)能加速查詢。它有助于避免多重排序操作,并且在其它方面還能簡化優(yōu)化器的工作。例如:SELECT,rcvbles.balance,……othercolumnsFROMcust,rcvblesWHEREcust.customer_id=rcvlbes.customer_idANDrcvblls.balance>0ANDcust.postcode>“98000”O(jiān)RDERBY如果這個(gè)查詢要被執(zhí)行多次而不止一次,能夠把全部未付款的客戶找出來放在一種視圖中,并按客戶的名字進(jìn)行排序:CREATEVIEWDBO.V_CUST_RCVLBESASSELECT,rcvbles.balance,……othercolumnsFROMcust,rcvblesWHEREcust.customer_id=rcvlbes.customer_idANDrcvblls.balance>0ORDERBY然后下列面的方式在視圖中查詢:SELECT*FROMV_CUST_RCVLBESWHEREpostcode>“98000”視圖中的行要比主表中的行少,并且物理次序就是所規(guī)定的次序,減少了磁盤I/O,因此查詢工作量能夠得到大幅減少。23、能用DISTINCT的就不用GROUPBYSELECTOrderIDFROMDetailsWHEREUnitPrice>10GROUPBYOrderID可改為:SELECTDISTINCTOrderIDFROMDetailsWHEREUnitPrice>1024.能用UNIONALL就不要用UNIONUNIONALL不執(zhí)行SELECTDISTINCT函數(shù),這樣就會(huì)減少諸多不必要的資源35.盡量不要用SELECTINTO語句。SELECTINOT語句會(huì)造成表鎖定,制止其它顧客訪問該表。上面我們提到的是某些基本的提高查詢速度的注意事項(xiàng)但是在更多的狀況下往往需要重復(fù)實(shí)驗(yàn)比較不同的語句以得到最佳方案。最佳的辦法固然是測(cè)試,看實(shí)現(xiàn)相似功效的SQL語句哪個(gè)執(zhí)行時(shí)間最少,但是數(shù)據(jù)庫中如果數(shù)據(jù)量極少,是比較不出來的,這時(shí)能夠用查看執(zhí)行計(jì)劃,即:把實(shí)現(xiàn)相似功效的多條SQL語句考到查詢分析器,按CTRL+L看查所運(yùn)用的索引,表掃描次數(shù)(這兩個(gè)對(duì)性能影響最大),總體上看詢成本比例即可。三、算法的優(yōu)化盡量避免使用游標(biāo),由于游標(biāo)的效率較差,如果游標(biāo)操作的數(shù)據(jù)超出1萬行,那么就應(yīng)當(dāng)考慮改寫。.使用基于游標(biāo)的辦法或臨時(shí)表辦法之前,應(yīng)先尋找基于集的解決方案來解決問題,基于集的辦法普通更有效。與臨時(shí)表同樣,游標(biāo)并不是不可使用。對(duì)小型數(shù)據(jù)集使用FAST_FORWARD游標(biāo)普通要優(yōu)于其它逐行解決辦法,特別是在必須引用幾個(gè)表才干獲得所需的數(shù)據(jù)時(shí)。在成果集中涉及“累計(jì)”的例程普通要比使用游標(biāo)執(zhí)行的速度快。如果開發(fā)時(shí)間允許,基于游標(biāo)的辦法和基于集的辦法都能夠嘗試一下,看哪一種辦法的效果更加好。游標(biāo)提供了對(duì)特定集合中逐行掃描的手段,普通使用游標(biāo)逐行遍歷數(shù)據(jù),根據(jù)取出的數(shù)據(jù)不同條件進(jìn)行不同的操作。特別對(duì)多表和大表定義的游標(biāo)(大的數(shù)據(jù)集合)循環(huán)很容易使程序進(jìn)入一種漫長的等特甚至死機(jī)。在有些場(chǎng)合,有時(shí)也非得使用游標(biāo),此時(shí)也可考慮將符合條件的數(shù)據(jù)行轉(zhuǎn)入臨時(shí)表中,再對(duì)臨時(shí)表定義游標(biāo)進(jìn)行操作,可時(shí)性能得到明顯提高。(例如:對(duì)內(nèi)統(tǒng)計(jì)第一版)封裝存儲(chǔ)過程四、建立高效的索引創(chuàng)立索引普通有下列兩個(gè)目的:維護(hù)被索引列的唯一性和提供快速訪問表中數(shù)據(jù)的方略。大型數(shù)據(jù)庫有兩種索引即簇索引和非簇索引,一種沒有簇索引的表是按堆構(gòu)造存儲(chǔ)數(shù)據(jù),全部的數(shù)據(jù)均添加在表的尾部,而建立了簇索引的表,其數(shù)據(jù)在物理上會(huì)按照簇索引鍵的次序存儲(chǔ),一種表只允許有一種簇索引,因此,根據(jù)B樹構(gòu)造,能夠理解添加任何一種索引均能提高按索引列查詢的速度,但會(huì)減少插入、更新、刪除操作的性能,特別是當(dāng)填充因子(FillFactor)較大時(shí)。因此對(duì)索引較多的表進(jìn)行頻繁的插入、更新、刪除操作,建表和索引時(shí)因設(shè)立較小的填充因子,方便在各數(shù)據(jù)頁中留下較多的自由空間,減少頁分割及重新組織的工作。索引是從數(shù)據(jù)庫中獲取數(shù)據(jù)的最高效方式之一。95%的數(shù)據(jù)庫性能問題都能夠采用索引技術(shù)得到解決。作為一條規(guī)則,我普通對(duì)邏輯主鍵使用唯一的成組索引,對(duì)系統(tǒng)鍵(作為存儲(chǔ)過程)采用唯一的非成組索引,對(duì)任何外鍵列[字段]采用非成組索引。但是,索引就象是鹽,太多了菜就咸了。你得考慮數(shù)據(jù)庫的空間有多大,表如何進(jìn)行訪問,尚有這些訪問與否重要用作讀寫。事實(shí)上,您能夠把索引理解為一種特殊的目錄。微軟的SQLSERVER提供了兩種索引:聚集索引(clusteredindex,也稱聚類索引、簇集索引)和非聚集索引(nonclusteredindex,也稱非聚類索引、非簇集索引)。下面,我們舉例來闡明一下聚集索引和非聚集索引的區(qū)別:其實(shí),我們的漢語字典的正文本身就是一種聚集索引。例如,我們要查“安”字,就會(huì)很自然地翻開字典的前幾頁,由于“安”的拼音是“an”,而按照拼音排序中文的字典是以英文字母“a”開頭并以“z”結(jié)尾的,那么“安”字就自然地排在字典的前部。如果您翻完了全部以“a”開頭的部分仍然找不到這個(gè)字,那么就闡明您的字典中沒有這個(gè)字;同樣的,如果查“張”字,那您也會(huì)將您的字典翻到最后部分,由于“張”的拼音是“zhang”。也就是說,字典的正文部分本身就是一種目錄,您不需要再去查其它目錄來找到您需要找的內(nèi)容。我們把這種正文內(nèi)容本身就是一種按照一定規(guī)則排列的目錄稱為“聚集索引”。如果您認(rèn)識(shí)某個(gè)字,您能夠快速地從自動(dòng)中查到這個(gè)字。但您也可能會(huì)碰到您不認(rèn)識(shí)的字,不懂得它的發(fā)音,這時(shí)候,您就不能按照剛剛的辦法找到您要查的字,而需要去根據(jù)“偏旁部首”查到您要找的字,然后根據(jù)這個(gè)字后的頁碼直接翻到某頁來找到您要找的字。但您結(jié)合“部首目錄”和“檢字表”而查到的字的排序并不是真正的正文的排序辦法,例如您查“張”字,我們能夠看到在查部首之后的檢字表中“張”的頁碼是672頁,檢字表中“張”的上面是“馳”字,但頁碼卻是63頁,“張”的下面是“弩”字,頁面是390頁。很顯然,這些字并不是真正的分別位于“張”字的上下方,現(xiàn)在您看到的持續(xù)的“馳、張、弩”三字事實(shí)上就是他們?cè)诜蔷奂饕械呐判?,是字典正文中的字在非聚集索引中的映射。我們能夠通過這種方式來找到您所需要的字,但它需要兩個(gè)過程,先找到目錄中的成果,然后再翻到您所需要的頁碼。我們把這種目錄純正是目錄,正文純正是正文的排序方式稱為“非聚集索引”。進(jìn)一步引申一下,我們能夠很容易的理解:每個(gè)表只能有一種聚集索引,由于目錄只能按照一種辦法進(jìn)行排序。(一)何時(shí)使用聚集索引或非聚集索引下面的表總結(jié)了何時(shí)使用聚集索引或非聚集索引(很重要)。動(dòng)作描述使用聚集索引使用非聚集索引列經(jīng)常被分組排序應(yīng)應(yīng)返回某范疇內(nèi)的數(shù)據(jù)應(yīng)不應(yīng)一種或極少不同值不應(yīng)不應(yīng)小數(shù)目的不同值應(yīng)不應(yīng)大數(shù)目的不同值不應(yīng)應(yīng)頻繁更新的列不應(yīng)應(yīng)外鍵列應(yīng)應(yīng)主鍵列應(yīng)應(yīng)頻繁修改索引列不應(yīng)應(yīng)事實(shí)上,我們能夠通過前面聚集索引和非聚集索引的定義的例子來理解上表。如:返回某范疇內(nèi)的數(shù)據(jù)一項(xiàng)。例如您的某個(gè)表有一種時(shí)間列,正好您把聚合索引建立在了該列,這時(shí)您查詢1月1日至10月1日之間的全部數(shù)據(jù)時(shí),這個(gè)速度就將是很快的,由于您的這本字典正文是按日期進(jìn)行排序的,聚類索引只需要找到要檢索的全部數(shù)據(jù)中的開頭和結(jié)尾數(shù)據(jù)即可;而不像非聚集索引,必須先查到目錄中查到每一項(xiàng)數(shù)據(jù)對(duì)應(yīng)的頁碼,然后再根據(jù)頁碼查到具體內(nèi)容。(二)結(jié)合實(shí)際,談索引使用的誤區(qū)理論的目的是應(yīng)用。即使我們剛剛列出了何時(shí)應(yīng)使用聚集索引或非聚集索引,但在實(shí)踐中以上規(guī)則卻很容易被無視或不能根據(jù)實(shí)際狀況進(jìn)行綜合分析。下面我們將根據(jù)在實(shí)踐中碰到的實(shí)際問題來談一下索引使用的誤區(qū),方便于大家掌握索引建立的辦法。1、主鍵就是聚集索引這種想法筆者認(rèn)為是極端錯(cuò)誤的,是對(duì)聚集索引的一種浪費(fèi)。即使SQLSERVER默認(rèn)是在主鍵上建立聚集索引的。普通,我們會(huì)在每個(gè)表中都建立一種ID列,以分辨每條數(shù)據(jù),并且這個(gè)ID列是自動(dòng)增大的,步長普通為1。我們的這個(gè)辦公自動(dòng)化的實(shí)例中的列Gid就是如此。此時(shí),如果我們將這個(gè)列設(shè)為主鍵,SQLSERVER會(huì)將此列默認(rèn)為聚集索引。這樣做有好處,就是能夠讓您的數(shù)據(jù)在數(shù)據(jù)庫中按照ID進(jìn)行物理排序,但筆者認(rèn)為這樣做意義不大。顯而易見,聚集索引的優(yōu)勢(shì)是很明顯的,而每個(gè)表中只能有一種聚集索引的規(guī)則,這使得聚集索引變得更加貴重。從我們前面談到的聚集索引的定義我們能夠看出,使用聚集索引的最大好處就是能夠根據(jù)查詢規(guī)定,快速縮小查詢范疇,避免全表掃描。在實(shí)際應(yīng)用中,由于ID號(hào)是自動(dòng)生成的,我們并不懂得每條統(tǒng)計(jì)的ID號(hào),因此我們很難在實(shí)踐中用ID號(hào)來進(jìn)行查詢。這就使讓ID號(hào)這個(gè)主鍵作為聚集索引成為一種資源浪費(fèi)。另首先,讓每個(gè)ID號(hào)都不同的字段作為聚集索引也不符合“大數(shù)目的不同值狀況下不應(yīng)建立聚合索引”規(guī)則;固然,這種狀況只是針對(duì)顧客經(jīng)常修改統(tǒng)計(jì)內(nèi)容,特別是索引項(xiàng)的時(shí)候會(huì)負(fù)作用,但對(duì)于查詢速度并沒有影響。在辦公自動(dòng)化系統(tǒng)中,無論是系統(tǒng)首頁顯示的需要顧客簽收的文獻(xiàn)、會(huì)議還是顧客進(jìn)行文獻(xiàn)查詢等任何狀況下進(jìn)行數(shù)據(jù)查詢都離不開字段的是“日期”尚有顧客本身的“顧客名”。普通,辦公自動(dòng)化的首頁會(huì)顯示每個(gè)顧客尚未簽收的文獻(xiàn)或會(huì)議。即使我們的where語句能夠僅僅限制現(xiàn)在顧客尚未簽收的狀況,但如果您的系統(tǒng)已建立了很長時(shí)間,并且數(shù)據(jù)量很大,那么,每次每個(gè)顧客打開首頁的時(shí)候都進(jìn)行一次全表掃描,這樣做意義是不大的,絕大多數(shù)的顧客1個(gè)月前的文獻(xiàn)都已經(jīng)瀏覽過了,這樣做只能徒增數(shù)據(jù)庫的開銷而已。事實(shí)上,我們完全能夠讓顧客打開系統(tǒng)首頁時(shí),數(shù)據(jù)庫僅僅查詢這個(gè)顧客近3個(gè)月來未閱覽的文獻(xiàn),通過“日期”這個(gè)字段來限制表掃描,提高查詢速度。如果您的辦公自動(dòng)化系統(tǒng)已經(jīng)建立的2年,那么您的首頁顯示速度理論上將是原來速度8倍,甚至更快。2、只要建立索引就能明顯提高查詢速度事實(shí)上,我們能夠發(fā)現(xiàn)上面的例子中,第2、3條語句完全相似,且建立索引的字段也相似;不同的僅是前者在fariqi字段上建立的是非聚合索引,后者在此字段上建立的是聚合
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度交通安全免責(zé)協(xié)議書:交通安全責(zé)任劃分3篇
- 二零二五年度民辦學(xué)校辦學(xué)許可證轉(zhuǎn)讓及教學(xué)資源共享合同3篇
- 2025年度公司單位員工帶薪年假與人事合同實(shí)施細(xì)則3篇
- 二零二五年度養(yǎng)殖場(chǎng)租賃與飼料原料采購合作協(xié)議2篇
- 二零二五年度農(nóng)機(jī)租賃與農(nóng)產(chǎn)品深加工合作合同3篇
- 2025年度勞動(dòng)合同解除通知及離職證明模板3篇
- 二零二五年度股東退出與公司社會(huì)責(zé)任履行協(xié)議2篇
- 2025年度農(nóng)村保潔員服務(wù)區(qū)域及質(zhì)量合同
- 2025年度城市綠化石子供應(yīng)及養(yǎng)護(hù)服務(wù)合同3篇
- 2025年度年度高風(fēng)險(xiǎn)戶外活動(dòng)意外事故免責(zé)協(xié)議3篇
- 換熱器課程設(shè)計(jì)
- 部編版三年級(jí)語文上冊(cè)期末試卷(含答案)
- 公司扭虧解困方案
- 信訪十種情形追責(zé)問責(zé)制度
- 大型儲(chǔ)罐施工工法倒裝法安裝
- 氫能與燃料電池電動(dòng)汽車第5章 氫與燃料電池
- 餐飲店購銷合同
- 文化資源數(shù)字化技術(shù)有哪些
- 2023年杭州聯(lián)合銀行校園招聘筆試歷年高頻考點(diǎn)試題答案詳解
- 灌裝軋蓋機(jī)和供瓶機(jī)設(shè)備驗(yàn)證方案
- 《國家中藥飲片炮制規(guī)范》全文
評(píng)論
0/150
提交評(píng)論