


下載本文檔
版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、我們做軟件開發的,大部分人都離不開跟數據庫打交道,特別是erp開發的,跟數據庫打交道更是頻繁,存儲過程動不動就是上千行,如果數據量大,人員流動大,那么我么還能保證下一段時間系統還能流暢的運行嗎?我么還能保證下一個人能看懂我么的存儲過程嗎?那么我結合公司平時的培訓和平時個人工作經驗和大家分享一下,希望對大家有幫助。要知道sql語句,我想我們有必要知道sqlserver查詢分析器怎么執行我么sql語句的,我么很多人會看執行計劃,或者用profile來監視和調優查詢語句或者存儲過程慢的原因,但是如果我們知道查詢分析器的執行邏輯順序,下手的時候就胸有成竹,那么下手是不是有把握點呢?一:查詢的邏輯執行順
2、序FROM<left_table><join_type>JOIN<right_table>(2)ON<join_condition>WHERE<where_condition>GROUPBY<group_by_list>WITHcube|rollupHAVING<having_condition>(8)SELECT(9)DISTINCT(11)<top_specification><select_list>(10)ORDERBY<order_by_list>標準的SQL的解析
3、順序為:.FROM子句組裝來自不同數據源的數據.WHERE子句基于指定的條件對記錄進行篩選.GROUPBY子句將數據劃分為多個分組.使用聚合函數進行計算.使用HAVING子句篩選分組.計算所有的表達式.使用ORDERBY對結果集進行排序二執行順序:1.FROM:對FROM子句中前兩個表執行笛卡爾積生成虛擬表vt12.ON:對vt1表應用ON篩選器只有滿足<join_condition>為真的行才被插入vt23.OUTER(join):如果指定了OUTERJOIN保留表(preservedtable)中未找到的行將行作為外部行添加到vt2生成t3如果from包含兩個以上表則對上一個聯
4、結生成的結果表和下一個表重復執行步驟和步驟直接結束WHERE:對vt3應用WHERE篩選器只有使<where_condition>為true的行才被插入vt4GROUPBY:按GROUPBY子句中的列列表對vt4中的行分組生成vt5CUBE|ROLLUP:把超組(supergroups)插入vt6生成vt6HAVING:對vt6應用HAVING篩選器只有使<having_condition>為true的組才插入vt78.SELECT:處理select列表產生vt89.DISTINCT:將重復的行從vt8中去除產生vt910.ORDERBY:將vt9的行按orderby子
5、句中的列列表排序生成一個游標vc1011.TOP:從vc10的開始處選擇指定數量或比例的行生成vt11并返回調用者看到這里,那么用過linqtosql的語法有點相似啊?如果我們我們了解了sqlserver執行順序,那么我們就接下來進一步養成日常sql好習慣,也就是在實現功能同時有考慮性能的思想,數據庫是能進行集合運算的工具,我們應該盡量的利用這個工具,所謂集合運算實際就是批量運算,就是盡量減少在客戶端進行大數據量的循環操作,而用SQL語句或者存儲過程代替。三、只返回需要的數據返回數據到客戶端至少需要數據庫提取數據、網絡傳輸數據、客戶端接收數據以及客戶端處理數據等環節,如果返回不需要的數據,就會
6、增加服務器、網絡和客戶端的無效勞動,其害處是顯而易見的,避免這類事件需要注意:A、橫向來看,(1) 不要寫SELECT*的語句,而是選擇你需要的字段。當在SQL語句中連接多個表時,請使用表的別名并把別名前綴于每個Column上.這樣一來,就可以減少解析的時間并減少那些由Column歧義引起的語法錯誤。11 01如有表tablel(ID,col1)和table2(ID,col2)0203SelectA.ID,A.coll,B.col20405-SelectA.ID,coll,col2-不要這么寫,不利于將來程序擴展0607fromtablelAinnerjointable2BonA.ID=B.I
7、DWhere0809B、縱向來看,10(1)合理寫WHERE句,不要寫沒有WHERESQL®句。12(2)SELECTTOPN*-沒有WHERE件的用此替代四:盡量少做重復的工作A、控制同一語句的多次執行,特別是一些基礎數據的多次執行是很多程序員很少注意的。B、減少多次的數據轉換,也許需要數據轉換是設計的問題,但是減少次數是程序員可以做到的。C、杜絕不必要的子查詢和連接表,子查詢在執行計劃一般解釋成外連接,多余的連接表帶來額外的開銷。D、合并對同一表同一條件的多次UPDATE,比如UPDATEEMPLOYEESETFNAME='HAIWER'WHEREEMP_ID=&
8、#39;VPA30890F'UPDATEEMPLOYEESETLNAME='YANG'WHEREEMP_ID='VPA30890F'這兩個語句應該合并成以下一個語句UPDATEEMPLOYEESETFNAME='HAIWER',LNAME='YANG'WHEREEMP_ID='VPA30890F'E、UPDATE操作不要拆成DELETE操作+INSERT操作的形式,雖然功能相同,但是性能差別是很大的。五、注意臨時表和表變量的用法在復雜系統中,臨時表和表變量很難避免,關于臨時表和表變量的用法,需要注意:A、如
9、果語句很復雜,連接太多,可以考慮用臨時表和表變量分步完成。B、如果需要多次用到一個大表的同一部分數據,考慮用臨時表和表變量暫存這部分數據。C、如果需要綜合多個表的數據,形成一個結果,可以考慮用臨時表和表變量分步匯總這多個表的數據。D、其他情況下,應該控制臨時表和表變量的使用。E、關于臨時表和表變量的選擇,很多說法是表變量在內存,速度快,應該首選表變量,但是在實際使用中發現,主要考慮需要放在臨時表的數據量,在數據量較多的情況下,臨時表的速度反而更快。(2)執行時間段與預計執行時間(多長)F、關于臨時表產生使用SELECTINTO和CREATETABLE+INSERTINTO的選擇,一般情況下,S
10、ELECTINTO會比CREATETABLE+INSERTINTO的方法快彳艮多,但是SELECTINTO會鎖定TEMPDB的系統表SYSOBJECTS、SYSINDEXES、SYSCOLUMNS,在多用戶并發環境下,容易阻塞其他進程,所以我的建議是,在并發系統中,盡量使用CREATETABLE+INSERTINTO,而大數據量的單個語句使用中,使用SELECTINTO。六、子查詢的用法(1)子查詢是一個SELECT查詢,它嵌套在SELECT、INSERT、UPDATE、DELETE語句或其它子查詢中。任何允許使用表達式的地方都可以使用子查詢,子查詢可以使我們的編程靈活多樣,可以用來實現一些特
11、殊的功能。但是在性能上,往往一個不合適的子查詢用法會形成一個性能瓶頸。如果子查詢的條件中使用了其外層的表的字段,這種子查詢就叫作相關子查詢。相關子查詢可以用IN、NOTIN、EXISTS、NOTEXISTS弓I入。關于相關子查詢,應該注意:(1)A、NOTIN、NOTEXISTS的相關子查詢可以改用LEFTJOIN代替寫法。比如:SELECTPUB_NAMEFROMPUBLISHERSWHEREPUB_IDNOTIN(SELECTPUB_IDFROMTITLESWHERETYPE='BUSINESS')可以改寫成:SELECTA.PUB_NAMEFROMPUBLISHERSAL
12、EFTJOINTITLESBONB.TYPE='BUSINESS'ANDA.PUB_ID=B.PUB_IDWHEREB.PUB_IDISNULL01SELECTTITLEFROMTITLES02WHERENOTEXISTS03(SELECTTITLE_IDFROMSALES04WHERETITLE_ID=TITLES.TITLE_ID)05可以改寫成:06SELECTTITLE07FROMTITLESLEFTJOINSALES08ONSALES.TITLE_ID=TITLES.TITLE_ID09WHERESALES.TITLE_IDISNULL“B、如果保證子查詢沒有重復,I
13、N、EXISTS的相關子查詢可以用10INNERJOIN代替。比如:SELECTPUB_NAMEFROMPUBLISHERSWHEREPUB_IDIN(SELECTPUB_IDFROMTITLESWHERETYPE='BUSINESS')17可以改寫成:SELECTA.PUB_NAME-SELECTDISTINCTA.PUB_NAMEFROMPUBLISHERSAINNERJOINTITLESBONB.TYPE='BUSINESS'ANDA.PUB_ID=B.PUB_IDC、IN的相關子查詢用EXISTS代替,比如SELECTPUB_NAMEFROMPUBLIS
14、HERSWHEREPUB_IDIN(SELECTPUB_IDFROMTITLESWHERETYPE='BUSINESS')5可以用下面語句代替:6 SELECTPUB_NAMEFROMPUBLISHERSWHEREEXISTS(SELECT1FROMTITLESWHERETYPE='BUSINESS'ANDPUB_ID=PUBLISHERS.PUB_ID)7 D不要用COUNT(*)勺子查詢判斷是否存在記錄,最好用LEFTJOIN或者EXISTS,比如有人寫這樣的語句:01SELECTJOB_DESCFROMJOBS0WHERE(SELECTCOUNT(*)FR
15、OMEMPLOYEEWHEREJOB_ID=JOBS.JOB_ID)=00應該改成:304SELECTJOBS.JOB_DESCFROMJOBSLEFTJOINEMPLOYEE05ONEMPLOYEE.JOB_ID=JOBS.JOB_ID06WHEREEMPLOYEE.EMP_IDSNULL070SELECTJOBDESCFROMJOBS-0WHERE(SELECTCOUNT(*)FROMEMPLOYEEWHEREJOB_ID=JOBS.JOB_ID)<>010應該改成:11SELECTJOB_DESCFROMJOBSWHEREEXISTS(SELECT1FROMEMPLOYEEW
16、HEREJOB_ID=JOBS.JOB_ID)七:盡量使用索引建立索引后,并不是每個查詢都會使用索引,在使用索引的情況下,索引的使用效率也會有很大的差別。只要我們在查詢語句中沒有強制指定索引,索引的選擇和使用方法是SQLSERVER的優化器自動作的選擇,而它選擇的根據是查詢語句的條件以及相關表的統計信息,這就要求我們在寫SQL語句的時候盡量使得優化器可以使用索引。為了使得優化器能高效使用索引,寫語句的時候應該注息:1 (1A、不要對索引字段進行運算,而要想辦法做變換,比如SELECTIDFROMTWHERENUM/2=100應改為:SELECTIDFROMTWHERENUM=100*2SELE
17、CTIDFROMTWHERENUM/2=NUM1如果NUhW索引應改為:SELECTIDFROMTWHERENUM=NUM1*2如果NUM有索引則不應該改。01發現過這樣的語句:02SELECT年,月,金額FROM結余表WHERE100*年+月=2010*100+1003應該改為:04SELECT年,月,金額FROM結余表WHERE年=2010AN或=100506B、不要對索引字段進行格式轉換07日期字段的例子:12 08WHERECONVERT(VARCHAR(1(®期字段,120)='2010-07-15'09應該改為WHER日期字段='2010-07-1
18、5'AND日期字段<'2010-07-16'11ISNULL轉換的例子:WHEREISNULL(字段,'')<>''應改為:WHERI?段<>''WHEREISNULL(字段,'')=''不應修改WHEREISNULL(字段,'F')='T'應改為:WHER日段='T'WHEREISNULL(字段,'F')<>'T'不應修改01C、不要對索引字段使用函數02WHERELE
19、FT(NAME,3)='ABC'或者WHERESUBSTRING(NAME,1,3)='ABC'03應改為:WHERENAMELIKE'ABC%'04日期查詢的例子:05WHEREDATEDIFF(DAY,日期,'2010-06-30')=006應改為:WHERE日期>='2010-06-30'AND日期<'2010-07-01'07WHEREDATEDIFF(DAY,日期,'2010-06-30')>008應改為:WHERE日期<'2010-06-3
20、0'09WHEREDATEDIFF(DAY,日期,'2010-06-30')>=0應改為:WHERE日期<'2010-07-01'WHEREDATEDIFF(DAY,日期,'2010-06-30')<0應改為:WHERE日期>='2010-07-01'WHEREDATEDIFF(DAY,日期,'2010-06-30')<=0應改為:WHERE日期>='2010-06-30'D、不要對索引字段進行多字段連接比如:WHEREFAME+'.'+L
21、NAME='HAIWEI.YANG'應改為:WHEREFNAME='HAIWEI'ANDLNAME='YANG'八:多表連接的連接條件對索引的選擇有著重要的意義,所以我們在寫連接條件條件的時候需要特別注意。A、多表連接的時候,連接條件必須寫全,寧可重復,不要缺漏。B、連接條件盡量使用聚集索引C、注意ON、WHERE和HAVING部分條件的區別ON是最先執行,WHERE次之,HAVING最后,因為ON是先把不符合條件的記錄過濾后才進行統計,它就可以減少中間運算要處理的數據,按理說應該速度是最快的,WHERE也應該比HAVING快點的,因為它過濾數據后才進行SUM,在兩個表聯接時才用ON的,所以在一個表的時候,就剩下WHERE跟HAVING比較了1考慮聯接優先順序:(1)INNERJOINLEF
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 工業地產整裝技術與環保材料應用
- 工業污染治理與環境保護策略
- 工業污染源監測及治理方案
- 工業污染防治與循環經濟
- 工業機器人技術及其產業升級策略
- 工業生產中的質量控制與檢測技術
- 工業自動化系統的遠程監控與控制
- 工業機械設備的使用與日常維護
- 工業環境影響評價與法規要求
- 工業自動化與智能工廠的發展趨勢
- 2025年廣東省廣州市白云區中考語文二模試卷
- 2025年天津市河西區中考二模數學試題(含部分答案)
- 醫院培訓課件:《藥品不良反應報告和監測工作簡介》
- 2025 屆九年級初三畢業典禮校長講話:星河長明共赴新程
- 2025年伽師縣(中小學、幼兒園)教師招聘考試模擬試題及答案
- 醫院培訓中心管理制度
- GM/T 0009-2023SM2密碼算法使用規范
- 中等職業教育與普通高中教育融合發展路徑研究
- 網約車轉讓合同協議書
- 2024年安徽省初中學業水平考試生物試題含答案
- 2024年浙江省中考英語試題卷(含答案解析)
評論
0/150
提交評論