整理的數(shù)據(jù)庫查詢(SQL)效率分析、優(yōu)化、注意事項_第1頁
整理的數(shù)據(jù)庫查詢(SQL)效率分析、優(yōu)化、注意事項_第2頁
整理的數(shù)據(jù)庫查詢(SQL)效率分析、優(yōu)化、注意事項_第3頁
整理的數(shù)據(jù)庫查詢(SQL)效率分析、優(yōu)化、注意事項_第4頁
整理的數(shù)據(jù)庫查詢(SQL)效率分析、優(yōu)化、注意事項_第5頁
已閱讀5頁,還剩11頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

目錄一、 關(guān)于SQL查詢效率,100w數(shù)據(jù),查詢只要1秒。 2二、 SQL提高查詢效率注意事項 4三、 提高SQL查詢效率(要點與技巧) 9四、 建立索引與不建立索引的一個查詢效率分析: 10五、 如何提高SQL語言的查詢效率 11六、 使用SQL語句時應(yīng)注意以下幾點 13七、 ORACAL中的應(yīng)用案例分析 14 關(guān)于SQL查詢效率,100w數(shù)據(jù),查詢只要1秒。機器情況:p4:2.4內(nèi)存:1GOs:windows2003數(shù)據(jù)庫:mssqlserver2000目的:查詢性能測試,比較兩種查詢的性能SQL查詢效率stepbystep:step1.--建表createtablet_userinfo(useridintidentity(1,1)primarykeynonclustered,nickvarchar(50)notnulldefault'',classidintnotnulldefault0,writetimedatetimenotnulldefaultgetdate())go--建索引createclusteredindexix_userinfo_classidont_userinfo(classid)gostep2.--插入數(shù)據(jù),耗時08:27,需要耐心等待declare@iintdeclare@kintdeclare@nickvarchar(10)set@i=1while@i<1000000beginset@k=@i%10set@nick=convert(varchar,@i)insertintot_userinfo(nick,classid,writetime)values(@nick,@k,getdate())set@i=@i+1endstep3.--where查詢,耗時8秒,夠長的selecttop20userid,nick,classid,writetimefromt_userinfowhereuseridnotin(selecttop900000useridfromt_userinfoorderbyuseridasc)step4. --where查詢,耗時1秒,太快了吧,不可以思議selecta.userid,b.nick,b.classid,b.writetimefrom(selecttop20a.useridfrom(selecttop900020useridfromt_userinfoorderbyuseridasc)aorderbya.useriddesc)ainnerjoint_userinfobona.userid=b.useridorderbya.useridascstep5--where查詢,耗時2秒selecttop20userid,nick,classid,writetimefromt_userinfowhereclassid=1anduseridnotin(selecttop90000useridfromt_userinfowhereclassid=1orderbyuseridasc)step6--where查詢,分析器顯示不到1秒selecta.userid,b.nick,b.classid,b.writetimefrom(selecttop20a.useridfrom(selecttop90000useridfromt_userinfowhereclassid=1orderbyuseridasc)aorderbya.useriddesc)ainnerjoint_userinfobona.userid=b.useridorderbya.useridasc查詢效率分析:子查詢?yōu)榇_保消除重復(fù)值,必須為外部查詢的每個結(jié)果都處理嵌套查詢。在這種情況下可以考慮用聯(lián)接查詢來取代。如果要用子查詢,那就用EXISTS替代IN、用NOTEXISTS替代NOTIN。因為EXISTS引入的子查詢只是測試是否存在符合子查詢中指定條件的行,效率較高。無論在哪種情況下,NOTIN都是最低效的。因為它對子查詢中的表執(zhí)行了一個全表遍歷。建立合理的索引,避免掃描多余數(shù)據(jù),避免表掃描!幾百萬條數(shù)據(jù),照樣幾十毫秒完成查詢。SQL提高查詢效率注意事項對查詢進(jìn)行優(yōu)化,應(yīng)盡量避免全表掃描,首先應(yīng)考慮在where及orderby涉及的列上建立索引。應(yīng)盡量避免在where子句中對字段進(jìn)行null值判斷,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,如:selectidfromtwherenumisnull--可以在num上設(shè)置默認(rèn)值0,確保表中num列沒有null值,然后這樣查詢:selectidfromtwherenum=0應(yīng)盡量避免在where子句中使用!=或<>操作符,否則將引擎放棄使用索引而進(jìn)行全表掃描。應(yīng)盡量避免在where子句中使用or來連接條件,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,如:selectidfromtwherenum=10ornum=20--可以這樣查詢:selectidfromtwherenum=10unionallselectidfromtwherenum=20in和notin也要慎用,否則會導(dǎo)致全表掃描,如:selectidfromtwherenumin(1,2,3)--對于連續(xù)的數(shù)值,能用between就不要用in了:selectidfromtwherenumbetween1and3下面的查詢也將導(dǎo)致全表掃描:selectidfromtwherenamelike'%abc%'--若要提高效率,可以考慮全文檢索如果在where子句中使用參數(shù),也會導(dǎo)致全表掃描。因為SQL只有在運行時才會解析局部變量,但優(yōu)化程序不能將訪問計劃的選擇推遲到運行時;它必須在編譯時進(jìn)行選擇。然而,如果在編譯時建立訪問計劃,變量的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將進(jìn)行全表掃描:selectidfromtwherenum=@num可以改為強制查詢使用索引:selectidfromtwith(index(索引名))wherenum=@num應(yīng)盡量避免在where子句中對字段進(jìn)行表達(dá)式操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。如:selectidfromtwherenum/2=100應(yīng)改為:selectidfromtwherenum=100*2應(yīng)盡量避免在where子句中對字段進(jìn)行函數(shù)操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。如:selectidfromtwheresubstring(name,1,3)='abc'--name以abc開頭的idselectidfromtwheredatediff(day,createdate,'2005-11-30')=0--‘2005-11-30’生成的id應(yīng)改為:selectidfromtwherenamelike'abc%'selectidfromtwherecreatedate>='2005-11-30'andcreatedate<'2005-12-1'不要在where子句中的“=”左邊進(jìn)行函數(shù)、算術(shù)運算或其他表達(dá)式運算,否則系統(tǒng)將可能無法正確使用索引。在使用索引字段作為條件時,如果該索引是復(fù)合索引,那么必須使用到該索引中的第一個字段作為條件時才能保證系統(tǒng)使用該索引,否則該索引將不會被使用,并且應(yīng)盡可能的讓字段順序與索引順序相一致。不要寫一些沒有意義的查詢,如需要生成一個空表結(jié)構(gòu):selectcol1,col2into#tfromtwhere1=0這類代碼不會返回任何結(jié)果集,但是會消耗系統(tǒng)資源的,應(yīng)改成這樣:createtable#t(...)很多時候用exists代替in是一個好的選擇:selectnumfromawherenumin(selectnumfromb)用下面的語句替換:selectnumfromawhereexists(select1frombwherenum=a.num)并不是所有索引對查詢都有效,SQL是根據(jù)表中數(shù)據(jù)來進(jìn)行查詢優(yōu)化的,當(dāng)索引列有大量數(shù)據(jù)重復(fù)時,SQL查詢可能不會去利用索引,如一表中有字段sex,male、female幾乎各一半,那么即使在sex上建了索引也對查詢效率起不了作用。索引并不是越多越好,索引固然可以提高相應(yīng)的select的效率,但同時也降低了insert及update的效率,因為insert或update時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數(shù)最好不要超過6個,若太多則應(yīng)考慮一些不常使用到的列上建的索引是否有必要。應(yīng)盡可能的避免更新clustered索引數(shù)據(jù)列,因為clustered索引數(shù)據(jù)列的順序就是表記錄的物理存儲順序,一旦該列值改變將導(dǎo)致整個表記錄的順序的調(diào)整,會耗費相當(dāng)大的資源。若應(yīng)用系統(tǒng)需要頻繁更新clustered索引數(shù)據(jù)列,那么需要考慮是否應(yīng)將該索引建為clustered索引。盡量使用數(shù)字型字段,若只含數(shù)值信息的字段盡量不要設(shè)計為字符型,這會降低查詢和連接的性能,并會增加存儲開銷。這是因為引擎在處理查詢和連接時會逐個比較字符串中每一個字符,而對于數(shù)字型而言只需要比較一次就夠了。盡可能的使用varchar/nvarchar代替char/nchar,因為首先變長字段存儲空間小,可以節(jié)省存儲空間,其次對于查詢來說,在一個相對較小的字段內(nèi)搜索效率顯然要高些。任何地方都不要使用select*fromt,用具體的字段列表代替“*”,不要返回用不到的任何字段。盡量使用表變量來代替臨時表。如果表變量包含大量數(shù)據(jù),請注意索引非常有限(只有主鍵索引)。避免頻繁創(chuàng)建和刪除臨時表,以減少系統(tǒng)表資源的消耗。臨時表并不是不可使用,適當(dāng)?shù)厥褂盟鼈兛梢允鼓承├谈行?,例如,?dāng)需要重復(fù)引用大型表或常用表中的某個數(shù)據(jù)集時。但是,對于一次性事件,最好使用導(dǎo)出表。在新建臨時表時,如果一次性插入數(shù)據(jù)量很大,那么可以使用selectinto代替createtable,避免造成大量log,以提高速度;如果數(shù)據(jù)量不大,為了緩和系統(tǒng)表的資源,應(yīng)先createtable,然后insert。如果使用到了臨時表,在存儲過程的最后務(wù)必將所有的臨時表顯式刪除,先truncatetable,然后droptable,這樣可以避免系統(tǒng)表的較長時間鎖定。盡量避免使用游標(biāo),因為游標(biāo)的效率較差,如果游標(biāo)操作的數(shù)據(jù)超過1萬行,那么就應(yīng)該考慮改寫。使用基于游標(biāo)的方法或臨時表方法之前,應(yīng)先尋找基于集的解決方案來解決問題,基于集的方法通常更有效。與臨時表一樣,游標(biāo)并不是不可使用。對小型數(shù)據(jù)集使用FAST_FORWARD游標(biāo)通常要優(yōu)于其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數(shù)據(jù)時。在結(jié)果集中包括“合計”的例程通常要比使用游標(biāo)執(zhí)行的速度快。如果開發(fā)時間允許,基于游標(biāo)的方法和基于集的方法都可以嘗試一下,看哪一種方法的效果更好。在所有的存儲過程和觸發(fā)器的開始處設(shè)置SETNOCOUNTON,在結(jié)束時設(shè)置SETNOCOUNTOFF。無需在執(zhí)行存儲過程和觸發(fā)器的每個語句后向客戶端發(fā)送DONE_IN_PROC消息。盡量避免大事務(wù)操作,提高系統(tǒng)并發(fā)能力。盡量避免向客戶端返回大數(shù)據(jù)量,若數(shù)據(jù)量過大,應(yīng)該考慮相應(yīng)需求是否合理。避免將字段設(shè)為“允許為空”數(shù)據(jù)表設(shè)計要規(guī)范深入分析數(shù)據(jù)操作所要對數(shù)據(jù)庫進(jìn)行的操作盡量不要使用臨時表多多使用事務(wù)盡量不要使用游標(biāo)避免死鎖要注意讀寫鎖的使用不要打開大的數(shù)據(jù)集不要使用服務(wù)器端游標(biāo)在程序編碼時使用大數(shù)據(jù)量的數(shù)據(jù)庫不要給“性別”列創(chuàng)建索引注意超時問題不要使用Select*在細(xì)節(jié)表中插入紀(jì)錄時,不要在主表執(zhí)行SelectMAX(ID)盡量不要使用TEXT數(shù)據(jù)類型使用參數(shù)查詢不要使用Insert導(dǎo)入大批的數(shù)據(jù)學(xué)會分析查詢使用參照完整性用INNERJOIN和LEFTJOIN代替Where提高SQL查詢效率(要點與技巧)技巧一:問題類型:ACCESS數(shù)據(jù)庫字段中含有日文片假名或其它不明字符時查詢會提示內(nèi)存溢出。解決方法:修改查詢語句sql="select*fromtablenamewherecolumnlike'%"&word&"%'"改為sql="select*fromtablename"rs.filter="columnlike'%"&word&"%'"技巧二:問題類型:如何用簡易的辦法實現(xiàn)類似百度的多關(guān)鍵詞查詢(多關(guān)鍵詞用空格或其它符號間隔)。解決方法:'//用空格分割查詢字符串ck=split(word,"")'//得到分割后的數(shù)量sck=UBound(ck)sql="select*tablenamewhere"在一個字段中查詢Fori=0TosckSQL=SQL&tempJoinWord&"("&_"columnlike'"&ck(i)&"%')"tempJoinWord="and"Next在二個字段中同時查詢Fori=0TosckSQL=SQL&tempJoinWord&"("&_"columnlike'"&ck(i)&"%'or"&_"column1like'"&ck(i)&"%')"tempJoinWord="and"Next技巧三:大大提高查詢效率的幾種技巧盡量不要使用or,使用or會引起全表掃描,將大大降低查詢效率。經(jīng)過實踐驗證,charindex()并不比前面加%的like更能提高查詢效率,并且charindex()會使索引失去作用(指sqlserver數(shù)據(jù)庫)columnlike'%"&word&"%'會使索引不起作用columnlike'"&word&"%'會使索引起作用(去掉前面的%符號)(指sqlserver數(shù)據(jù)庫)'%"&word&"%'與'"&word&"%'在查詢時的區(qū)別:比如你的字段內(nèi)容為一個容易受傷的女人'%"&word&"%':會通配所有字符串,不論查“受傷”還是查“一個”,都會顯示結(jié)果。'"&word&"%':只通配前面的字符串,例如查“受傷”是沒有結(jié)果的,只有查“一個”,才會顯示結(jié)果。字段提取要按照“需多少、提多少”的原則,避免“select*”,盡量使用“select字段1,字段2,字段3”。實踐證明:每少提取一個字段,數(shù)據(jù)的提取速度就會有相應(yīng)的提升。提升的速度還要看您舍棄的字段的大小來判斷。orderby按聚集索引列排序效率最高。一個sqlserver數(shù)據(jù)表只能建立一個聚集索引,一般默認(rèn)為ID,也可以改為其它的字段。為你的表建立適當(dāng)?shù)乃饕?,建立索引可以使你的查詢速度提高幾十幾百倍。(指sqlserver數(shù)據(jù)庫)建立索引與不建立索引的一個查詢效率分析:環(huán)境:數(shù)據(jù)庫:Sqlserver表:News字段Id:自動編號Title:文章標(biāo)題Author:作者Content:內(nèi)容Star:優(yōu)先級Addtime:時間記錄:100萬條測試機器:P42.8/1G內(nèi)存/IDE硬盤方案1:--主鍵Id,默認(rèn)為聚集索引,不建立其它非聚集索引select*fromNewswhereTitlelike'%"&word&"%'orAuthorlike'%"&word&"%'orderbyIddesc--從字段Title和Author中模糊檢索,按Id排序查詢時間:50秒方案2:--主鍵Id,默認(rèn)為聚集索引,在Title、Author、Star上建立非聚集索引select*fromNewswhereTitlelike'"&word&"%'orAuthorlike'"&word&"%'orderbyIddesc--從字段Title和Author中模糊檢索,按Id排序查詢時間:2-2.5秒方案3:--主鍵Id,默認(rèn)為聚集索引,在Title、Author、Star上建立非聚集索引select*fromNewswhereTitlelike'"&word&"%'orAuthorlike'"&word&"%'orderbyStardesc--從字段Title和Author中模糊檢索,按Star排序查詢時間:2秒方案4:--主鍵Id,默認(rèn)為聚集索引,在Title、Author、Star上建立非聚集索引select*fromNewswhereTitlelike'"&word&"%'orAuthorlike'"&word&"%'--從字段Title和Author中模糊檢索,不排序查詢時間:1.8-2秒方案5:--主鍵Id,默認(rèn)為聚集索引,在Title、Author、Star上建立非聚集索引select*fromNewswhereTitlelike'"&word&"%'或select*fromNewswhereAuthorlike'"&word&"%'--從字段Title或Author中檢索,不排序查詢時間:1秒如何提高SQL語言的查詢效率由于SQL是面向結(jié)果而不是面向過程的查詢語言,所以一般支持SQL語言的大型關(guān)系型數(shù)據(jù)庫都使用一個基于查詢成本的優(yōu)化器,為即時查詢提供一個最佳的執(zhí)行策略。對于優(yōu)化器,輸入是一條查詢語句,輸出是一個執(zhí)行策略。一條SQL查詢語句可以有多種執(zhí)行策略,優(yōu)化器將估計出全部執(zhí)行方法中所需時間最少的所謂成本最低的那一種方法。所有優(yōu)化都是基于用記所使用的查詢語句中的where子句,優(yōu)化器對where子句中的優(yōu)化主要用搜索參數(shù)(SerachArgument)。搜索參數(shù)的核心思想就是數(shù)據(jù)庫使用表中字段的索引來查詢數(shù)據(jù),而不必直接查詢記錄中的數(shù)據(jù)。帶有=、<、<=、>、>=等操作符的條件語句可以直接使用索引,如下列是搜索參數(shù):emp_id="10001"salary>3000a=1andc=7而下列則不是搜索參數(shù):salary=emp_salarydep_id!=10salary*12>=3000a=1orc=7應(yīng)當(dāng)盡可能提供一些冗余的搜索參數(shù),使優(yōu)化器有更多的選擇余地。請看以下3種方法:第一種方法:selectemployee.emp_name,department.dep_namefromdepartment,employeewhere(employee.dep_id=department.dep_id)and(department.dep_code="01")and(employee.dep_code="01");它的搜索分析結(jié)果如下:Estimate2I/OoperationsScandepartmentusingprimarykeyforrowswheredep_codeequals"01"Estimategettinghere1timesScanemployeesequentiallyEstimategettinghere5times第二種方法:selectemployee.emp_name,department.dep_namefromdepartment,employeewhere(employee.dep_id=department.dep_id)and(department.dep_code="01");它的搜索分析結(jié)果如下:Estimate2I/OoperationsScandepartmentusingprimarykeyforrowswheredep_codeequals"01"Estimategettinghere1timesScanemployeesequentiallyEstimategettinghere5times第一種方法與第二種運行效率相同,但第一種方法最好,因為它為優(yōu)化器提供了更多的選擇機會。第三種方法:selectemployee.emp_name,department.dep_namefromdepartment,employeewhere(employee.dep_id=department.dep_id)and(employee.dep_code="01");這種方法最不好,因為它無法使用索引,也就是無法優(yōu)化……使用SQL語句時應(yīng)注意以下幾點1、避免使用不兼容的數(shù)據(jù)類型。例如,F(xiàn)loat和Integer,Char和Varchar,Binary和LongBinary不兼容的。數(shù)據(jù)類型的不兼容可能使優(yōu)化器無法執(zhí)行一些本可以進(jìn)行的優(yōu)化操作。例如:selectemp_nameformemployeewheresalary>3000;在此語句中若salary是Float類型的,則優(yōu)化器很難對其進(jìn)行優(yōu)化,因為3000是個整數(shù),我們應(yīng)在編程時使用3000.0而不要等運行時讓DBMS進(jìn)行轉(zhuǎn)化。2、盡量不要使用表達(dá)式,因它在編繹時是無法得到的,所以SQL只能使用其平均密度來估計將要命中的記錄數(shù)。3、避免對搜索參數(shù)使用其他的數(shù)學(xué)操作符。如:selectemp_namefromemployeewheresalary*12>3000;應(yīng)改為:selectemp_namefromemployeewheresalary>250;4、避免使用!=或<>等這樣的操作符,因為它會使系統(tǒng)無法使用索引,而只能直接搜索表中的數(shù)據(jù)。ORACAL中的應(yīng)用案例分析一個1600萬數(shù)據(jù)表--短信上行表TBL_SMS_MO結(jié)構(gòu):CREATETABLETBL_SMS_MO(SMS_IDNUMBER,MO_IDVARCHAR2(50),MOBILEVARCHAR2(11),SPNUMBERVARCHAR2(20),MESSAGEVARCHAR2(150),TRADE_CODEVARCHAR2(20),LINK_IDVARCHAR2(50),GATEWAY_IDNU

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論