處理百萬級以上的數據提高查詢速度的方法

1.應盡量避免在where子句中使用!=<>操作符,否則將引擎放棄使用索引而進行全表掃描。

2.對查詢進行優化,應盡量避免全表掃描,首先應考慮在whereorderby涉及的列上建立索引。

3.應盡量避免在where子句中對字段進行null值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
selectidfromtwherenumisnull
可以在num上設置默認值0,確保表中num列沒有null值,然后這樣查詢:
selectidfromtwherenum=0

4.應盡量避免在where子句中使用or來連接條件,否則將導致引擎放棄使用索引而進行全表掃描,如:
selectidfromtwherenum=10ornum=20
可以這樣查詢:
selectidfromtwherenum=10
unionall
selectidfromtwherenum=20

5.下面的查詢也將導致全表掃描:(不能前置百分號)
selectidfromtwherenamelike%abc%
若要提高效率,可以考慮全文檢索。

6.innotin也要慎用,否則會導致全表掃描,如:
selectidfromtwherenumin(1,2,3)
對于連續的數值,能用
between就不要用in了:
selectidfromtwherenumbetween1and3

7.如果在where子句中使用參數,也會導致全表掃描。因為SQL只有在運行時才會解析局部變量,但優化程序不能將訪問計劃的選擇推遲到運行時;它必須在編譯時進行選擇。然而,如果在編譯時建立訪問計劃,變量的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:
selectidfromtwherenum=@num
可以改為強制查詢使用索引:
selectidfromtwith(index(索引名))wherenum=@num

8.應盡量避免在where子句中對字段進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
selectidfromtwherenum/2=100
應改為:
selectidfromtwherenum=100*2

9.應盡量避免在where子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:
selectidfromtwheresubstring(name,1,3)=’abc’–name以abc開頭的id
selectidfromtwheredatediff(day,createdate,’2005-11-30′)=0–’2005-11-30′生成的id
應改為:
selectidfromtwherenamelike‘abc%
selectidfromtwherecreatedate>=2005-11-30andcreatedate<2005-12-1

10.不要在where子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。

11.在使用索引字段作為條件時,如果該索引是復合索引,那么必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引,否則該索引將不會被使用,并且應盡可能的讓字段順序與索引順序相一致。

12.不要寫一些沒有意義的查詢,如需要生成一個空表結構:
selectcol1,col2into#tfromtwhere1=0
這類代碼不會返回任何結果集,但是會消耗系統資源的,應改成這樣:
createtable#t(…)

13.很多時候用exists代替in是一個好的選擇:
selectnumfromawherenumin(selectnumfromb)
用下面的語句替換:
selectnumfromawhereexists(select1frombwherenum=a.num)

14.并不是所有索引對查詢都有效,SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重復時,SQL查詢可能不會去利用索引,如一表中有字段sex,male、female幾乎各一半,那么即使在sex上建了索引也對查詢效率起不了作用。

15.索引并不是越多越好,索引固然可以提高相應的select的效率,但同時也降低了insertupdate的效率,因為insertupdate時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有必要。

16.應盡可能的避免更新clustered索引數據列,因為clustered索引數據列的順序就是表記錄的物理存儲順序,一旦該列值改變將導致整個表記錄的順序的調整,會耗費相當大的資源。若應用系統需要頻繁更新clustered索引數據列,那么需要考慮是否應將該索引建為clustered索引。

17.盡量使用數字型字段,若只含數值信息的字段盡量不要設計為字符型,這會降低查詢和連接的性能,并會增加存儲開銷。這是因為引擎在處理查詢和連接時會逐個比較字符串中每一個字符,而對于數字型而言只需要比較一次就夠了。

18.盡可能的使用varchar/nvarchar代替char/nchar,因為首先變長字段存儲空間小,可以節省存儲空間,其次對于查詢來說,在一個相對較小的字段內搜索效率顯然要高些。

19.任何地方都不要使用select*fromt,用具體的字段列表代替“*”,不要返回用不到的任何字段。

20.盡量使用表變量來代替臨時表。如果表變量包含大量數據,請注意索引非常有限(只有主鍵索引)。

21.避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。

22.臨時表并不是不可使用,適當地使用它們可以使某些例程更有效,例如,當需要重復引用大型表或常用表中的某個數據集時。但是,對于一次性事件,最好使用導出表。

23.在新建臨時表時,如果一次性插入數據量很大,那么可以使用selectinto代替createtable,避免造成大量log,以提高速度;如果數據量不大,為了緩和系統表的資源,應先createtable,然后insert。

24.如果使用到了臨時表,在存儲過程的最后務必將所有的臨時表顯式刪除,先truncatetable,然后droptable,這樣可以避免系統表的較長時間鎖定。

25.盡量避免使用游標,因為游標的效率較差,如果游標操作的數據超過1萬行,那么就應該考慮改寫。

26.使用基于游標的方法或臨時表方法之前,應先尋找基于集的解決方案來解決問題,基于集的方法通常更有效。

27.與臨時表一樣,游標并不是不可使用。對小型數據集使用FAST_FORWARD游標通常要優于其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數據時。在結果集中包括“合計”的例程通常要比使用游標執行的速度快。如果開發時間允許,基于游標的方法和基于集的方法都可以嘗試一下,看哪一種方法的效果更好。

28.在所有的存儲過程和觸發器的開始處設置SETNOCOUNTON,在結束時設置SETNOCOUNTOFF。無需在執行存儲過程和觸發器的每個語句后向客戶端發送DONE_IN_PROC消息。

29.盡量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。

30.盡量避免大事務操作,提高系統并發能力。



查詢速度慢的原因:

1、沒有索引或者沒有用到索引(這是查詢慢最常見的問題,是程序設計的缺陷)

2、I/O吞吐量小,形成了瓶頸效應。

3、沒有創建計算列導致查詢不優化。

4、內存不足

5、網絡速度慢

6、查詢出的數據量過大(可以采用多次查詢,其他的方法降低數據量)

7、鎖或者死鎖(這也是查詢慢最常見的問題,是程序設計的缺陷)

8、sp_lock,sp_who,活動的用戶查看,原因是讀寫競爭資源。

9、返回了不必要的行和列

10、查詢語句不好,沒有優化

可以通過如下方法來優化查詢

1、把數據、日志、索引放到不同的I/O設備上,增加讀取速度,以前可以將Tempdb應放在RAID0上,SQL2000不在支持。數據量(尺寸)越大,提高I/O越重要.

2、縱向、橫向分割表,減少表的尺寸(sp_spaceuse)

3、升級硬件

4、根據查詢條件,建立索引,優化索引、優化訪問方式,限制結果集的數據量。注意填充因子要適當(最好是使用默認值0)。索引應該盡量小,使用字節數小的列建索引好(參照索引的創建),不要對有限的幾個值的字段建單一索引如性別字段

5、提高網速;

6、擴大服務器的內存,Windows2000和SQLserver2000能支持4-8G的內存。配置虛擬內存:虛擬內存大小應基于計算機上并發運行的服務進行配置。運行MicrosoftSQLServer?2000時,可考慮將虛擬內存大小設置為計算機中安裝的物理內存的1.5倍。如果另外安裝了全文檢索功能,并打算運行Microsoft搜索服務以便執行全文索引和查詢,可考慮:將虛擬內存大小配置為至少是計算機中安裝的物理內存的3倍。將SQLServermaxservermemory服務器配置選項配置為物理內存的1.5倍(虛擬內存大小設置的一半)。



8、如果是使用like進行查詢的話,簡單的使用index是不行的,但是全文索引,耗空間。like'a%'使用索引like'%a'不使用索引用like'%a%'查詢時,查詢耗時和字段值總長度成正比,所以不能用CHAR類型,而是VARCHAR。對于字段的值很長的建全文索引。

9、DBServer和APPLicationServer分離;OLTP和OLAP分離

11、重建索引DBCCREINDEX,DBCCINDEXDEFRAG,收縮數據和日志DBCCSHRINKDB,DBCCSHRINKFILE.設置自動收縮日志.對于大的數據庫不要設置數據庫自動增長,它會降低服務器的性能。在T-sql的寫法上有很大的講究,下面列出常見的要點:首先,DBMS處理查詢計劃的過程是這樣的:
1、查詢語句的詞法、語法檢查
2、將語句提交給DBMS的查詢優化器
3、優化器做代數優化和存取路徑的優化
4、由預編譯模塊生成查詢規劃
5、然后在合適的時間提交給系統處理執行
6、最后將執行結果返回給用戶其次,看一下SQLSERVER的數據存放的結構:一個頁面的大小為8K(8060)字節,8個頁面為一個盤區,按照B樹存放。


13、在查詢Select語句中用Where字句限制返回的行數,避免表掃描,如果返回不必要的數據,浪費了服務器的I/O資源,加重了網絡的負擔降低性能。如果表很大,在表掃描的期間將表鎖住,禁止其他的聯接訪問表,后果嚴重。


16、用Profiler來跟蹤查詢,得到查詢所需的時間,找出SQL的問題所在;用索引優化器優化索引

17、注意UNion和UNionall的區別。UNIONall好

18、注意使用DISTINCT,在沒有必要時不要用,它同UNION一樣會使查詢變慢。重復的記錄在查詢里是沒有問題的

19、查詢時不要返回不需要的行、列

20、用sp_configure'querygovernorcostlimit'或者SETQUERY_GOVERNOR_COST_LIMIT來限制查詢消耗的資源。當評估查詢消耗的資源超出限制時,服務器自動取消查詢,在查詢之前就扼殺掉。SETLOCKTIME設置鎖的時間

21、用selecttop100/10Percent來限制用戶返回的行數或者SETROWCOUNT來限制操作的行

22、在SQL2000以前,一般不要用如下的字句“ISNULL","<>","!=","!>","!<","NOT","NOTEXISTS","NOTIN","NOTLIKE",and"LIKE'%500'",因為他們不走索引全是表掃描。
也不要在WHere字句中的列名加函數,如Convert,substring等,如果必須用函數的時候,創建計算列再創建索引來替代.還可以變通寫法:
WHERESUBSTRING(firstname,1,1)='m'改為WHEREfirstnamelike'm%'(索引掃描),一定要將函數和列名分開。并且索引不能建得太多和太大。
NOTIN會多次掃描表,使用EXISTS、NOTEXISTSIN,LEFTOUTERJOIN來替代,特別是左連接,而Exists比IN更快,最慢的是NOT操作.如果列的值含有空,以前它的索引不起作用,現在2000的優化器能夠處理了。相同的是ISNULL,“NOT","NOTEXISTS","NOTIN"能優化她,而”<>”等還是不能優化,用不到索引。


24、如果使用了IN或者OR等時發現查詢沒有走索引,使用顯示申明指定索引:SELECT*FROMPersonMember(INDEX=IX_Title)WHEREprocessidIN(‘男’,‘女’)

25、將需要查詢的結果預先計算好放在表中,查詢的時候再SELECT。這在SQL7.0以前是最重要的手段。例如醫院的住院費計算。

26MIN()和MAX()能使用到合適的索引


28、如果要插入大的二進制值到Image列,使用存儲過程,千萬不要用內嵌INsert來插入(不知JAVA是否)。因為這樣應用程序首先將二進制值轉換成字符串(尺寸是它的兩倍),服務器受到字符后又將他轉換成二進制值.存儲過程就沒有這些動作:方法:Createprocedurep_insertasinsertintotable(Fimage)values(@image),在前臺調用這個存儲過程傳入二進制參數,這樣處理速度明顯改善。

29、Between在某些時候比IN速度更快,Between能夠更快地根據索引找到范圍。用查詢優化器可見到差別。select*fromchineseresumewheretitlein('','')Select*fromchineseresumewherebetween''and''是一樣的。由于in會在比較多次,所以有時會慢些。


32、用OR的字句可以分解成多個查詢,并且通過UNION連接多個查詢。他們的速度只同是否使用索引有關,如果查詢需要用到聯合索引,用UNIONall執行的效率更高.多個OR的字句沒有用到索引,改寫成UNION的形式再試圖與索引匹配。一個關鍵的問題是否用到索引。

34、沒有必要時不要用DISTINCT和ORDERBY,這些動作可以改在客戶端執行。它們增加了額外的開銷。這同UNION和UNIONALL一樣的道理。SELECTtop20ad.companyname,comid,position,ad.referenceid,worklocation,convert(varchar(10),ad.postDate,120)aspostDate1,workyear,degreedescriptionFROMjobcn_query.dbo.COMPANYAD_queryadwherereferenceIDin('JCNAD00329667','JCNAD132168','JCNAD00337748','JCNAD00338345','JCNAD00333138','JCNAD00303570','JCNAD00303569','JCNAD00303568','JCNAD00306698','JCNAD00231935','JCNAD00231933','JCNAD00254567','JCNAD00254585','JCNAD00254608','JCNAD00254607','JCNAD00258524','JCNAD00332133','JCNAD00268618','JCNAD00279196','JCNAD00268613')orderbypostdatedesc

35、在IN后面值的列表中,將出現最頻繁的值放在最前面,出現得最少的放在最后面,減少判斷的次數

36、當用SELECTINTO時,它會鎖住系統表(sysobjects,sysindexes等等),阻塞其他的連接的存取。創建臨時表時用顯示申明語句,而不是selectINTO.droptablet_lxhbegintranselect*intot_lxhfromchineseresumewherename='XYZ'--commit在另一個連接中SELECT*fromsysobjects可以看到SELECTINTO會鎖住系統表,Createtable也會鎖系統表(不管是臨時表還是系統表)。所以千萬不要在事物內使用它!!!這樣的話如果是經常要用的臨時表請使用實表,或者臨時表變量。

37、一般在GROUPBY個HAVING字句之前就能剔除多余的行,所以盡量不要用它們來做剔除行的工作。他們的執行順序應該如下最優:select的Where字句選擇所有合適的行,GroupBy用來分組個統計行,Having字句用來剔除多余的分組。這樣GroupBy個Having的開銷小,查詢快.對于大的數據行進行分組和Having十分消耗資源。如果GroupBY的目的不包括計算,只是分組,那么用Distinct更快

38、一次更新多條記錄比分多次更新每次一條快,就是說批處理好

39、少用臨時表,盡量用結果集和Table類性的變量來代替它,Table類型的變量比臨時表好

40、在SQL2000下,計算字段是可以索引的,需要滿足的條件如下:

a、計算字段的表達是確定的
b、不能用在TEXT,
Ntext,Image數據類型
c、必須配制如下選項ANSI_NULLS
=ON,ANSI_PADDINGS=ON,…….


42、不要在一句話里再三的使用相同的函數,浪費資源,將結果放在變量里再調用更快

43SELECTCOUNT(*)的效率教低,盡量變通他的寫法,而EXISTS快.同時請注意區別:selectcount(Fieldofnull)fromTableselectcount(FieldofNOTnull)fromTable的返回值是不同的。


47、分析selectemp_nameformemployeewheresalary>3000在此語句中若salary是Float類型的,則優化器對其進行優化為Convert(float,3000),因為3000是個整數,我們應在編程時使用3000.0而不要等運行時讓DBMS進行轉化。同樣字符和整型數據的轉換。


1.應盡量避免在where子句中使用!=<>操作符,否則將引擎放棄使用索引而進行全表掃描。

2.對查詢進行優化,應盡量避免全表掃描,首先應考慮在whereorderby涉及的列上建立索引。

3.應盡量避免在where子句中對字段進行null值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
selectidfromtwherenumisnull
可以在num上設置默認值0,確保表中num列沒有null值,然后這樣查詢:
selectidfromtwherenum=0

4.應盡量避免在where子句中使用or來連接條件,否則將導致引擎放棄使用索引而進行全表掃描,如:
selectidfromtwherenum=10ornum=20
可以這樣查詢:
selectidfromtwherenum=10
unionall
selectidfromtwherenum=20

5.下面的查詢也將導致全表掃描:(不能前置百分號)
selectidfromtwherenamelike%abc%
若要提高效率,可以考慮全文檢索。

6.innotin也要慎用,否則會導致全表掃描,如:
selectidfromtwherenumin(1,2,3)
對于連續的數值,能用
between就不要用in了:
selectidfromtwherenumbetween1and3

7.如果在where子句中使用參數,也會導致全表掃描。因為SQL只有在運行時才會解析局部變量,但優化程序不能將訪問計劃的選擇推遲到運行時;它必須在編譯時進行選擇。然而,如果在編譯時建立訪問計劃,變量的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:
selectidfromtwherenum=@num
可以改為強制查詢使用索引:
selectidfromtwith(index(索引名))wherenum=@num

8.應盡量避免在where子句中對字段進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
selectidfromtwherenum/2=100
應改為:
selectidfromtwherenum=100*2

9.應盡量避免在where子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:
selectidfromtwheresubstring(name,1,3)=’abc’–name以abc開頭的id
selectidfromtwheredatediff(day,createdate,’2005-11-30′)=0–’2005-11-30′生成的id
應改為:
selectidfromtwherenamelike‘abc%
selectidfromtwherecreatedate>=2005-11-30andcreatedate<2005-12-1

10.不要在where子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。

11.在使用索引字段作為條件時,如果該索引是復合索引,那么必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引,否則該索引將不會被使用,并且應盡可能的讓字段順序與索引順序相一致。

12.不要寫一些沒有意義的查詢,如需要生成一個空表結構:
selectcol1,col2into#tfromtwhere1=0
這類代碼不會返回任何結果集,但是會消耗系統資源的,應改成這樣:
createtable#t(…)

13.很多時候用exists代替in是一個好的選擇:
selectnumfromawherenumin(selectnumfromb)
用下面的語句替換:
selectnumfromawhereexists(select1frombwherenum=a.num)

14.并不是所有索引對查詢都有效,SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重復時,SQL查詢可能不會去利用索引,如一表中有字段sex,male、female幾乎各一半,那么即使在sex上建了索引也對查詢效率起不了作用。

15.索引并不是越多越好,索引固然可以提高相應的select的效率,但同時也降低了insertupdate的效率,因為insertupdate時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有必要。

16.應盡可能的避免更新clustered索引數據列,因為clustered索引數據列的順序就是表記錄的物理存儲順序,一旦該列值改變將導致整個表記錄的順序的調整,會耗費相當大的資源。若應用系統需要頻繁更新clustered索引數據列,那么需要考慮是否應將該索引建為clustered索引。

17.盡量使用數字型字段,若只含數值信息的字段盡量不要設計為字符型,這會降低查詢和連接的性能,并會增加存儲開銷。這是因為引擎在處理查詢和連接時會逐個比較字符串中每一個字符,而對于數字型而言只需要比較一次就夠了。

18.盡可能的使用varchar/nvarchar代替char/nchar,因為首先變長字段存儲空間小,可以節省存儲空間,其次對于查詢來說,在一個相對較小的字段內搜索效率顯然要高些。

19.任何地方都不要使用select*fromt,用具體的字段列表代替“*”,不要返回用不到的任何字段。

20.盡量使用表變量來代替臨時表。如果表變量包含大量數據,請注意索引非常有限(只有主鍵索引)。

21.避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。

22.臨時表并不是不可使用,適當地使用它們可以使某些例程更有效,例如,當需要重復引用大型表或常用表中的某個數據集時。但是,對于一次性事件,最好使用導出表。

23.在新建臨時表時,如果一次性插入數據量很大,那么可以使用selectinto代替createtable,避免造成大量log,以提高速度;如果數據量不大,為了緩和系統表的資源,應先createtable,然后insert。

24.如果使用到了臨時表,在存儲過程的最后務必將所有的臨時表顯式刪除,先truncatetable,然后droptable,這樣可以避免系統表的較長時間鎖定。

25.盡量避免使用游標,因為游標的效率較差,如果游標操作的數據超過1萬行,那么就應該考慮改寫。

26.使用基于游標的方法或臨時表方法之前,應先尋找基于集的解決方案來解決問題,基于集的方法通常更有效。

27.與臨時表一樣,游標并不是不可使用。對小型數據集使用FAST_FORWARD游標通常要優于其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數據時。在結果集中包括“合計”的例程通常要比使用游標執行的速度快。如果開發時間允許,基于游標的方法和基于集的方法都可以嘗試一下,看哪一種方法的效果更好。

28.在所有的存儲過程和觸發器的開始處設置SETNOCOUNTON,在結束時設置SETNOCOUNTOFF。無需在執行存儲過程和觸發器的每個語句后向客戶端發送DONE_IN_PROC消息。

29.盡量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。

30.盡量避免大事務操作,提高系統并發能力。



查詢速度慢的原因:

1、沒有索引或者沒有用到索引(這是查詢慢最常見的問題,是程序設計的缺陷)

2、I/O吞吐量小,形成了瓶頸效應。

3、沒有創建計算列導致查詢不優化。

4、內存不足

5、網絡速度慢

6、查詢出的數據量過大(可以采用多次查詢,其他的方法降低數據量)

7、鎖或者死鎖(這也是查詢慢最常見的問題,是程序設計的缺陷)

8、sp_lock,sp_who,活動的用戶查看,原因是讀寫競爭資源。

9、返回了不必要的行和列

10、查詢語句不好,沒有優化

可以通過如下方法來優化查詢

1、把數據、日志、索引放到不同的I/O設備上,增加讀取速度,以前可以將Tempdb應放在RAID0上,SQL2000不在支持。數據量(尺寸)越大,提高I/O越重要.

2、縱向、橫向分割表,減少表的尺寸(sp_spaceuse)

3、升級硬件

4、根據查詢條件,建立索引,優化索引、優化訪問方式,限制結果集的數據量。注意填充因子要適當(最好是使用默認值0)。索引應該盡量小,使用字節數小的列建索引好(參照索引的創建),不要對有限的幾個值的字段建單一索引如性別字段

5、提高網速;

6、擴大服務器的內存,Windows2000和SQLserver2000能支持4-8G的內存。配置虛擬內存:虛擬內存大小應基于計算機上并發運行的服務進行配置。運行MicrosoftSQLServer?2000時,可考慮將虛擬內存大小設置為計算機中安裝的物理內存的1.5倍。如果另外安裝了全文檢索功能,并打算運行Microsoft搜索服務以便執行全文索引和查詢,可考慮:將虛擬內存大小配置為至少是計算機中安裝的物理內存的3倍。將SQLServermaxservermemory服務器配置選項配置為物理內存的1.5倍(虛擬內存大小設置的一半)。



8、如果是使用like進行查詢的話,簡單的使用index是不行的,但是全文索引,耗空間。like'a%'使用索引like'%a'不使用索引用like'%a%'查詢時,查詢耗時和字段值總長度成正比,所以不能用CHAR類型,而是VARCHAR。對于字段的值很長的建全文索引。

9、DBServer和APPLicationServer分離;OLTP和OLAP分離

11、重建索引DBCCREINDEX,DBCCINDEXDEFRAG,收縮數據和日志DBCCSHRINKDB,DBCCSHRINKFILE.設置自動收縮日志.對于大的數據庫不要設置數據庫自動增長,它會降低服務器的性能。在T-sql的寫法上有很大的講究,下面列出常見的要點:首先,DBMS處理查詢計劃的過程是這樣的:
1、查詢語句的詞法、語法檢查
2、將語句提交給DBMS的查詢優化器
3、優化器做代數優化和存取路徑的優化
4、由預編譯模塊生成查詢規劃
5、然后在合適的時間提交給系統處理執行
6、最后將執行結果返回給用戶其次,看一下SQLSERVER的數據存放的結構:一個頁面的大小為8K(8060)字節,8個頁面為一個盤區,按照B樹存放。


13、在查詢Select語句中用Where字句限制返回的行數,避免表掃描,如果返回不必要的數據,浪費了服務器的I/O資源,加重了網絡的負擔降低性能。如果表很大,在表掃描的期間將表鎖住,禁止其他的聯接訪問表,后果嚴重。


16、用Profiler來跟蹤查詢,得到查詢所需的時間,找出SQL的問題所在;用索引優化器優化索引

17、注意UNion和UNionall的區別。UNIONall好

18、注意使用DISTINCT,在沒有必要時不要用,它同UNION一樣會使查詢變慢。重復的記錄在查詢里是沒有問題的

19、查詢時不要返回不需要的行、列

20、用sp_configure'querygovernorcostlimit'或者SETQUERY_GOVERNOR_COST_LIMIT來限制查詢消耗的資源。當評估查詢消耗的資源超出限制時,服務器自動取消查詢,在查詢之前就扼殺掉。SETLOCKTIME設置鎖的時間

21、用selecttop100/10Percent來限制用戶返回的行數或者SETROWCOUNT來限制操作的行

22、在SQL2000以前,一般不要用如下的字句“ISNULL","<>","!=","!>","!<","NOT","NOTEXISTS","NOTIN","NOTLIKE",and"LIKE'%500'",因為他們不走索引全是表掃描。
也不要在WHere字句中的列名加函數,如Convert,substring等,如果必須用函數的時候,創建計算列再創建索引來替代.還可以變通寫法:
WHERESUBSTRING(firstname,1,1)='m'改為WHEREfirstnamelike'm%'(索引掃描),一定要將函數和列名分開。并且索引不能建得太多和太大。
NOTIN會多次掃描表,使用EXISTS、NOTEXISTSIN,LEFTOUTERJOIN來替代,特別是左連接,而Exists比IN更快,最慢的是NOT操作.如果列的值含有空,以前它的索引不起作用,現在2000的優化器能夠處理了。相同的是ISNULL,“NOT","NOTEXISTS","NOTIN"能優化她,而”<>”等還是不能優化,用不到索引。


24、如果使用了IN或者OR等時發現查詢沒有走索引,使用顯示申明指定索引:SELECT*FROMPersonMember(INDEX=IX_Title)WHEREprocessidIN(‘男’,‘女’)

25、將需要查詢的結果預先計算好放在表中,查詢的時候再SELECT。這在SQL7.0以前是最重要的手段。例如醫院的住院費計算。

26MIN()和MAX()能使用到合適的索引


28、如果要插入大的二進制值到Image列,使用存儲過程,千萬不要用內嵌INsert來插入(不知JAVA是否)。因為這樣應用程序首先將二進制值轉換成字符串(尺寸是它的兩倍),服務器受到字符后又將他轉換成二進制值.存儲過程就沒有這些動作:方法:Createprocedurep_insertasinsertintotable(Fimage)values(@image),在前臺調用這個存儲過程傳入二進制參數,這樣處理速度明顯改善。

29、Between在某些時候比IN速度更快,Between能夠更快地根據索引找到范圍。用查詢優化器可見到差別。select*fromchineseresumewheretitlein('','')Select*fromchineseresumewherebetween''and''是一樣的。由于in會在比較多次,所以有時會慢些。


32、用OR的字句可以分解成多個查詢,并且通過UNION連接多個查詢。他們的速度只同是否使用索引有關,如果查詢需要用到聯合索引,用UNIONall執行的效率更高.多個OR的字句沒有用到索引,改寫成UNION的形式再試圖與索引匹配。一個關鍵的問題是否用到索引。

34、沒有必要時不要用DISTINCT和ORDERBY,這些動作可以改在客戶端執行。它們增加了額外的開銷。這同UNION和UNIONALL一樣的道理。SELECTtop20ad.companyname,comid,position,ad.referenceid,worklocation,convert(varchar(10),ad.postDate,120)aspostDate1,workyear,degreedescriptionFROMjobcn_query.dbo.COMPANYAD_queryadwherereferenceIDin('JCNAD00329667','JCNAD132168','JCNAD00337748','JCNAD00338345','JCNAD00333138','JCNAD00303570','JCNAD00303569','JCNAD00303568','JCNAD00306698','JCNAD00231935','JCNAD00231933','JCNAD00254567','JCNAD00254585','JCNAD00254608','JCNAD00254607','JCNAD00258524','JCNAD00332133','JCNAD00268618','JCNAD00279196','JCNAD00268613')orderbypostdatedesc

35、在IN后面值的列表中,將出現最頻繁的值放在最前面,出現得最少的放在最后面,減少判斷的次數

36、當用SELECTINTO時,它會鎖住系統表(sysobjects,sysindexes等等),阻塞其他的連接的存取。創建臨時表時用顯示申明語句,而不是selectINTO.droptablet_lxhbegintranselect*intot_lxhfromchineseresumewherename='XYZ'--commit在另一個連接中SELECT*fromsysobjects可以看到SELECTINTO會鎖住系統表,Createtable也會鎖系統表(不管是臨時表還是系統表)。所以千萬不要在事物內使用它!!!這樣的話如果是經常要用的臨時表請使用實表,或者臨時表變量。

37、一般在GROUPBY個HAVING字句之前就能剔除多余的行,所以盡量不要用它們來做剔除行的工作。他們的執行順序應該如下最優:select的Where字句選擇所有合適的行,GroupBy用來分組個統計行,Having字句用來剔除多余的分組。這樣GroupBy個Having的開銷小,查詢快.對于大的數據行進行分組和Having十分消耗資源。如果GroupBY的目的不包括計算,只是分組,那么用Distinct更快

38、一次更新多條記錄比分多次更新每次一條快,就是說批處理好

39、少用臨時表,盡量用結果集和Table類性的變量來代替它,Table類型的變量比臨時表好

40、在SQL2000下,計算字段是可以索引的,需要滿足的條件如下:

a、計算字段的表達是確定的
b、不能用在TEXT,
Ntext,Image數據類型
c、必須配制如下選項ANSI_NULLS
=ON,ANSI_PADDINGS=ON,…….


42、不要在一句話里再三的使用相同的函數,浪費資源,將結果放在變量里再調用更快

43SELECTCOUNT(*)的效率教低,盡量變通他的寫法,而EXISTS快.同時請注意區別:selectcount(Fieldofnull)fromTableselectcount(FieldofNOTnull)fromTable的返回值是不同的。


47、分析selectemp_nameformemployeewheresalary>3000在此語句中若salary是Float類型的,則優化器對其進行優化為Convert(float,3000),因為3000是個整數,我們應在編程時使用3000.0而不要等運行時讓DBMS進行轉化。同樣字符和整型數據的轉換。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/444144.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/444144.shtml
英文地址,請注明出處:http://en.pswp.cn/news/444144.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

leetcode三道shell題

給定一個文本文件 file.txt&#xff0c;請只打印這個文件中的第十行。 示例: 假設 file.txt 有如下內容&#xff1a; Line 1 Line 2 Line 3 Line 4 Line 5 Line 6 Line 7 Line 8 Line 9 Line 10 你的腳本應當顯示第十行&#xff1a; Line 10 sed -n 10p file.txt 給定一個…

DateFormat(炸窩)

222&#xff1a;DateFormat方法的使用以及功能&#xff1a; java.text.DateFormat是日期或者時間格式化子類的抽象類&#xff0c;作用&#xff1a;可以幫我們完成日期和文本之間的轉換&#xff0c;也就是可以在Date對象與String對象之間進行來回轉換 格式化&#xff1a; 按照指…

劍指offer:3-7記錄

找出數組中重復的數字。 在一個長度為 n 的數組 nums 里的所有數字都在 0&#xff5e;n-1 的范圍內。數組中某些數字是重復的&#xff0c;但不知道有幾個數字重復了&#xff0c;也不知道每個數字重復了幾次。請找出數組中任意一個重復的數字。 示例 1&#xff1a; 輸入&#…

計算一個人出生了多少天(炸窩)

223&#xff1a; 小小練習&#xff1a; 請使用日期API來計算一個人出生了多少天&#xff1f; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner; public class zixuejava { public static void main(Str…

劍指offer:8-11記錄

用兩個棧實現一個隊列。隊列的聲明如下&#xff0c;請實現它的兩個函數 appendTail 和 deleteHead &#xff0c;分別完成在隊列尾部插入整數和在隊列頭部刪除整數的功能。(若隊列中沒有元素&#xff0c;deleteHead 操作返回 -1 ) 示例 1&#xff1a; 輸入&#xff1a; ["…

mysql命令

Mysql常見的命令總結&#xff1a; mysql服務的退出以及登陸 方式一&#xff1a;通過mysql自帶的客戶端&#xff0c;只限于root用戶 方式二&#xff1a;通過Windows自帶的客戶端&#xff0c; 登陸&#xff1a;mysql -uroot -p&#xff1b; 退出&#xff1a;exit或者是ctrlc&am…

leetcode343. 整數拆分

給定一個正整數 n&#xff0c;將其拆分為至少兩個正整數的和&#xff0c;并使這些整數的乘積最大化。 返回你可以獲得的最大乘積。 示例 1: 輸入: 2 輸出: 1 解釋: 2 1 1, 1 1 1。 示例 2: 輸入: 10 輸出: 36 解釋: 10 3 3 4, 3 3 4 36。 思路&#xff1a;動態規…

尚硅谷李老師Mysql基礎筆記

數據庫的相關概念 一&#xff1a;數據庫的好處 1.可以持久化數據到本地 2.結構化查詢 二&#xff1a;數據庫的常見概念 1.DB&#xff1a;數據庫&#xff0c;存儲數據的容器 2.DBMS:數據庫管理系統&#xff0c;又稱為數據庫軟件或數據庫產品&#xff0c;用于創建或者管理數據&…

劍指offer:12-17記錄

請設計一個函數&#xff0c;用來判斷在一個矩陣中是否存在一條包含某字符串所有字符的路徑。路徑可以從矩陣中的任意一格開始&#xff0c;每一步可以在矩陣中向左、右、上、下移動一格。如果一條路徑經過了矩陣的某一格&#xff0c;那么該路徑不能再次進入該格子。例如&#xf…

劍指offer:18-21記錄

給定單向鏈表的頭指針和一個要刪除的節點的值&#xff0c;定義一個函數刪除該節點。 返回刪除后的鏈表的頭節點。 注意&#xff1a;此題對比原題有改動 示例 1: 輸入: head [4,5,1,9], val 5 輸出: [4,1,9] 解釋: 給定你鏈表中值為 5 的第二個節點&#xff0c;那么在調用…

尚硅谷李老師筆記2

一&#xff1a;MySQL的背景 前身是瑞典的一家公司&#xff0c;MySQLAB 08年被sun公司收購 09年sun公司被oracle公司收購 二&#xff1a;MySQL的優點 1.開源&#xff0c;免費&#xff0c;成本低 2.性能高&#xff0c;移植性好 3.體積小&#xff0c;便于安裝 三&#xff1a;MyS…

劍指offer:22-25記錄

輸入一個鏈表&#xff0c;輸出該鏈表中倒數第k個節點。為了符合大多數人的習慣&#xff0c;本題從1開始計數&#xff0c;即鏈表的尾節點是倒數第1個節點。例如&#xff0c;一個鏈表有6個節點&#xff0c;從頭節點開始&#xff0c;它們的值依次是1、2、3、4、5、6。這個鏈表的倒…

尚硅谷李老師筆記3DQL

一&#xff1a;語法 select 查詢列表 from 表名 二&#xff1a;特點 1.查詢列表可以是字段&#xff0c;常量&#xff0c;表達式&#xff0c;函數&#xff0c;也可以是多個的組合結果 2.查詢結果是一張虛擬表 三&#xff1a;示例 1.查詢單個字段 select 字段名 from 表名 2.查…

java 防止表單重復提交

防止表單重復提交&#xff0c;或者是防止按F5 刷新提交表單。 在WEB開發中是經常會碰到這樣的問題的。 目前主流的解決方法有以下三種&#xff1a; 1、采用腳本來解決 2、重定向到別的頁面 3、使用s:token 標簽 由于我是使用S2SH來開發的&#xff0c;所以就選擇了第三種方法。 …

貪吃蛇源代碼111

#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <string.h> #include <time.h> const int H 8; //地圖的高 const int L 16; //地圖的長 char GameMap[H][L]; //游戲地圖 int key; //按鍵保存 int sum 1, over 0; //蛇…

劍指offer:26-30記錄

輸入兩棵二叉樹A和B&#xff0c;判斷B是不是A的子結構。(約定空樹不是任意一個樹的子結構) B是A的子結構&#xff0c; 即 A中有出現和B相同的結構和節點值。 例如: 給定的樹 A: 3 / \ 4 5 / \ 1 2 給定的樹 B&#xff1a; 4 / 1 返回 true&#xff0c;因為…

Calendar類 set方法 get方法 add方法

Calendar類 set方法 get方法 add方法 package asd; import java.util.*; public class zixue { public static void main(String[] args) { demo01();//實驗的是get()方法&#xff1b; demo02();//實驗的是set()方法&#xff1b; } //---------------------------------------…

劍指offer:31-32記錄(4道)

輸入兩個整數序列&#xff0c;第一個序列表示棧的壓入順序&#xff0c;請判斷第二個序列是否為該棧的彈出順序。假設壓入棧的所有數字均不相等。例如&#xff0c;序列 {1,2,3,4,5} 是某棧的壓棧序列&#xff0c;序列 {4,5,3,2,1} 是該壓棧序列對應的一個彈出序列&#xff0c;但…

炸窩Vector簡介

/** 1.Vector的介紹&#xff1a;* Vector<E>是所有單列集合的鼻祖&#xff0c;但是在JAVA1.2版本之后就被Collection集合所替代&#xff0c;Vector可以實現可增長的對象數組* 與數組一樣&#xff0c;它包含可以使用整數索引進行訪問的組件* 但是它的大小可以根據需要增加…

劍指offer:33-37記錄

輸入一個整數數組&#xff0c;判斷該數組是不是某二叉搜索樹的后序遍歷結果。如果是則返回 true&#xff0c;否則返回 false。假設輸入的數組的任意兩個數字都互不相同。 參考以下這顆二叉搜索樹&#xff1a; 5 / \ 2 6 / \ 1 3 示例 1&#xff1a; 輸入: [1,6,…