1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢(xún)
      選擇下列產(chǎn)品馬上在線(xiàn)溝通
      服務(wù)時(shí)間:8:30-17:00
      你可能遇到了下面的問(wèn)題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
      SQLServer數(shù)據(jù)庫(kù)sql優(yōu)化注意事項(xiàng)都有哪些

      SQL Server數(shù)據(jù)庫(kù)sql優(yōu)化注意事項(xiàng)都有哪些,相信很多沒(méi)有經(jīng)驗(yàn)的人對(duì)此束手無(wú)策,為此本文總結(jié)了問(wèn)題出現(xiàn)的原因和解決方法,通過(guò)這篇文章希望你能解決這個(gè)問(wèn)題。

      成都創(chuàng)新互聯(lián)于2013年開(kāi)始,先為滎經(jīng)等服務(wù)建站,滎經(jīng)等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢(xún)服務(wù)。為滎經(jīng)企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問(wèn)題。

      今天主要分享下sqlserver數(shù)據(jù)庫(kù)在做sql優(yōu)化時(shí)的25條注意事項(xiàng)。

      SQL優(yōu)化事項(xiàng)

      1. 應(yīng)盡量避免在 where 子句中對(duì)字段進(jìn)行 null 值判斷,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,如:

      SELECT ID FROM T WHERE NUM IS NULL

      可以在NUM上設(shè)置默認(rèn)值0,確保表中NUM列沒(méi)有NULL值,然后這樣查詢(xún):

      SELECT ID FROM T WHERE NUM=0

      2. 應(yīng)盡量避免在 where  子句中使用!=或<>操作符,否則將引擎放棄使用索引而進(jìn)行全表掃描。優(yōu)化器將無(wú)法通過(guò)索引來(lái)確定將要命中的行數(shù),因此需要搜索該表的所有行;

      3. 應(yīng)盡量避免在 where 子句中使用 OR來(lái)連接條件,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,如:

      SELECT ID FROM T WHERE NUM=10 OR NUM=20

      可以這樣查詢(xún):

      SELECT ID FROM T WHERE NUM=10 UNION ALL SELECT ID FROM T WHERE NUM=20

      4. IN和 NOT IN 也要慎用,因?yàn)镮N會(huì)使系統(tǒng)無(wú)法使用索引,而只能直接搜索表中的數(shù)據(jù)。如:

      SELECT ID FROM T WHERE NUM IN(1,2,3)

      對(duì)于連續(xù)的數(shù)值,能用 BETWEEN就不要用 IN了,如:

      SELECT ID FROM T WHERE NUM BETWEEN 1 AND 3

      5. 盡量避免在索引過(guò)的字符數(shù)據(jù)中,使用非打頭字母搜索。這也使得引擎無(wú)法利用索引。

      見(jiàn)如下例子:

      • SELECT * FROM T1 WHERE NAME LIKE '%L%' ----> 無(wú)索引

      • SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)='L' ----> 無(wú)索引

      • SELECT * FROM T1 WHERE NAME LIKE 'L%' ----> 有索引

      即使NAME字段建有索引,前兩個(gè)查詢(xún)依然無(wú)法利用索引完成加快操作,引擎不得不對(duì)全表所有數(shù)據(jù)逐條操作來(lái)完成任務(wù)。而第三個(gè)查詢(xún)能夠使用索引來(lái)加快操作。

      6. 必要時(shí)強(qiáng)制查詢(xún)優(yōu)化器使用某個(gè)索引,如在 where  子句中使用參數(shù),也會(huì)導(dǎo)致全表掃描。因?yàn)镾QL只有在運(yùn)行時(shí)才會(huì)解析局部變量,但優(yōu)化程序不能將訪(fǎng)問(wèn)計(jì)劃的選擇推遲到運(yùn)行時(shí);它必須在編譯時(shí)進(jìn)行選擇。然而,如果在編譯時(shí)建立訪(fǎng)問(wèn)計(jì)劃,變量的值還是未知的,因而無(wú)法作為索引選擇的輸入項(xiàng)。如下面語(yǔ)句將進(jìn)行全表掃描:

      SELECT ID FROM T WHERE NUM=@NUM

      可以改為強(qiáng)制查詢(xún)使用索引:

      SELECT ID FROM T WITH(INDEX(索引名)) WHERE NUM=@NUM

      7. 應(yīng)盡量避免在 where 子句中對(duì)字段進(jìn)行表達(dá)式操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。如:

      SELECT * FROM T1 WHERE F1/2=100

      應(yīng)改為:

      SELECT * FROM T1 WHERE F1=100*2  SELECT * FROM RECORD WHERE SUBSTRING(CARD_NO,1,4)='5378'

      應(yīng)改為:

      SELECT * FROM RECORD WHERE CARD_NO LIKE '5378%'  SELECT member_number, first_name, last_name FROM members   WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21

      應(yīng)改為:

      SELECT member_number, first_name, last_name FROM members  WHERE dateofbirth < DATEADD(yy,-21,GETDATE())

      即:任何對(duì)列的操作都將導(dǎo)致表掃描,它包括數(shù)據(jù)庫(kù)函數(shù)、計(jì)算表達(dá)式等等,查詢(xún)時(shí)要盡可能將操作移至等號(hào)右邊。

      8. 應(yīng)盡量避免在where子句中對(duì)字段進(jìn)行函數(shù)操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。如:

      select id from t where substring(name,1,3)='abc' ---->name以abc開(kāi)頭的id select id from t where datediff(day,createdate,'2005-11-30')=0 ---->'2005-11-30'生成的id

      應(yīng)改為:

      select id from t where name like 'abc%' select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'

      9. 不要在 where 子句中的“=”左邊進(jìn)行函數(shù)、算術(shù)運(yùn)算或其他表達(dá)式運(yùn)算,否則系統(tǒng)將可能無(wú)法正確使用索引。

      10. 在使用索引字段作為條件時(shí),如果該索引是復(fù)合索引,那么必須使用到該索引中的第一個(gè)字段作為條件時(shí)才能保證系統(tǒng)使用該索引,否則該索引將不會(huì)被使用,并且應(yīng)盡可能的讓字段順序與索引順序相一致。

      11. 很多時(shí)候用 exists是一個(gè)好的選擇,例:

      SELECT NUM FROM A WHERE NUM IN(SELECT NUM FROM B)

      用下面的語(yǔ)句替換:

      SELECT NUM FROM A WHERE EXISTS(SELECT 1 FROM B WHERE NUM=A.NUM) SELECT SUM(T1.C1) FROM T1 WHERE(SELECT COUNT(*)FROM T2 WHERE T2.C2=T1.C2>0)

      用下面的語(yǔ)句替換:

      SELECT SUM(T1.C1) FROM T1WHERE EXISTS(SELECT * FROM T2 WHERE T2.C2=T1.C2)

      兩者產(chǎn)生相同的結(jié)果,但是后者的效率顯然要高于前者。因?yàn)楹笳卟粫?huì)產(chǎn)生大量鎖定的表掃描或是索引掃描。

      如果你想校驗(yàn)表里是否存在某條紀(jì)錄,不要用count(*)那樣效率很低,而且浪費(fèi)服務(wù)器資源。可以用EXISTS代替。如:

      IF (SELECT COUNT(*) FROM table_name WHERE column_name = 'xxx')

      可以寫(xiě)成:

      IF EXISTS (SELECT * FROM table_name WHERE column_name = 'xxx')

      經(jīng)常需要寫(xiě)一個(gè)T_SQL語(yǔ)句比較一個(gè)父結(jié)果集和子結(jié)果集,從而找到是否存在在父結(jié)果集中有而在子結(jié)果集中沒(méi)有的記錄,如:

      SELECT a.hdr_key FROM hdr_tbl a ---- tbl a 表示tbl用別名a代替   WHERE NOT EXISTS (SELECT * FROM dtl_tbl b WHERE a.hdr_key = b.hdr_key)   SELECT a.hdr_key FROM hdr_tbl a   LEFT JOIN dtl_tbl b ON a.hdr_key = b.hdr_key WHERE b.hdr_key IS NULL   SELECT hdr_key FROM hdr_tbl   WHERE hdr_key NOT IN (SELECT hdr_key FROM dtl_tbl)

      三種寫(xiě)法都可以得到同樣正確的結(jié)果,但是效率依次降低。

      12. 盡量使用表變量來(lái)代替臨時(shí)表。如果表變量包含大量數(shù)據(jù),請(qǐng)注意索引非常有限(只有主鍵索引)。

      13. 避免頻繁創(chuàng)建和刪除臨時(shí)表,以減少系統(tǒng)表資源的消耗。

      14. 臨時(shí)表并不是不可使用,適當(dāng)?shù)厥褂盟鼈兛梢允鼓承├谈行В纾?dāng)需要重復(fù)引用大型表或常用表中的某個(gè)數(shù)據(jù)集時(shí)。但是,對(duì)于一次性事件,最好使用導(dǎo)出表。

      15. 在新建臨時(shí)表時(shí),如果一次性插入數(shù)據(jù)量很大,那么可以使用 select into 代替 create table,避免造成大量 log  ,以提高速度;如果數(shù)據(jù)量不大,為了緩和系統(tǒng)表的資源,應(yīng)先create table,然后insert。

      注意:SELECT INTO 語(yǔ)句會(huì)導(dǎo)致表鎖定,阻止其他用戶(hù)訪(fǎng)問(wèn)該表

      16. 如果使用到了臨時(shí)表,在存儲(chǔ)過(guò)程的最后務(wù)必將所有的臨時(shí)表顯式刪除,先 truncate table ,然后 drop table  ,這樣可以避免系統(tǒng)表的較長(zhǎng)時(shí)間鎖定。

      17. 在所有的存儲(chǔ)過(guò)程和觸發(fā)器的開(kāi)始處設(shè)置 SET NOCOUNT ON ,在結(jié)束時(shí)設(shè)置 SET NOCOUNT OFF  。無(wú)需在執(zhí)行存儲(chǔ)過(guò)程和觸發(fā)器的每個(gè)語(yǔ)句后向客戶(hù)端發(fā)送 DONE_IN_PROC 消息。

      18. 盡量避免大事務(wù)操作,提高系統(tǒng)并發(fā)能力。

      19. 盡量避免向客戶(hù)端返回大數(shù)據(jù)量,若數(shù)據(jù)量過(guò)大,應(yīng)該考慮相應(yīng)需求是否合理。

      20. 避免使用不兼容的數(shù)據(jù)類(lèi)型。例如float和int、char和varchar、binary和varbinary是不兼容的。數(shù)據(jù)類(lèi)型的不兼容可能使優(yōu)化器無(wú)法執(zhí)行一些本來(lái)可以進(jìn)行的優(yōu)化操作。例如:

      SELECT name FROM employee WHERE salary > 60000

      在這條語(yǔ)句中,如salary字段是money型的,則優(yōu)化器很難對(duì)其進(jìn)行優(yōu)化,因?yàn)?0000是個(gè)整型數(shù)。我們應(yīng)當(dāng)在編程時(shí)將整型轉(zhuǎn)化成為錢(qián)幣型,而不要等到運(yùn)行時(shí)轉(zhuǎn)化。

      21. 充分利用連接條件,在某種情況下,兩個(gè)表之間可能不只一個(gè)的連接條件,這時(shí)在 WHERE 子句中將連接條件完整的寫(xiě)上,有可能大大提高查詢(xún)速度。

      例:

      SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO  SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO  AND A.ACCOUNT_NO=B.ACCOUNT_NO

      第二句將比第一句執(zhí)行快得多。

      22. 使用視圖加速查詢(xún)

      把表的一個(gè)子集進(jìn)行排序并創(chuàng)建視圖,有時(shí)能加速查詢(xún)。它有助于避免多重排序操作,而且在其他方面還能簡(jiǎn)化優(yōu)化器的工作。例如:

      SELECT cust.name,rcvbles.balance,……other columns   FROM cust,rcvbles   WHERE cust.customer_id = rcvlbes.customer_id   AND rcvblls.balance>0   AND cust.postcode>98000  ORDER BY cust.name

      如果這個(gè)查詢(xún)要被執(zhí)行多次而不止一次,可以把所有未付款的客戶(hù)找出來(lái)放在一個(gè)視圖中,并按客戶(hù)的名字進(jìn)行排序:

      CREATE VIEW DBO.V_CUST_RCVLBES  AS  SELECT cust.name,rcvbles.balance,……other columns  FROM cust,rcvbles  WHERE cust.customer_id = rcvlbes.customer_id  AND rcvblls.balance>0  ORDER BY cust.name

      然后以下面的方式在視圖中查詢(xún):

      SELECT * FROM V_CUST_RCVLBES WHERE postcode>98000

      視圖中的行要比主表中的行少,而且物理順序就是所要求的順序,減少了磁盤(pán)I/O,所以查詢(xún)工作量可以得到大幅減少。

      23. 能用DISTINCT的就不用GROUP BY

      SELECT OrderID FROM Details WHERE UnitPrice > 10 GROUP BY OrderID

      可改為:

      SELECT DISTINCT OrderID FROM Details WHERE UnitPrice > 10

      24. 能用UNION ALL就不要用UNION

      UNION ALL不執(zhí)行SELECT DISTINCT函數(shù),這樣就會(huì)減少很多不必要的資源

      25. 盡量不要用SELECT INTO語(yǔ)句

      SELECT INOT 語(yǔ)句會(huì)導(dǎo)致表鎖定,阻止其他用戶(hù)訪(fǎng)問(wèn)該表。

      上面我們提到的是一些基本的提高查詢(xún)速度的注意事項(xiàng),但是在更多的情況下,往往需要反復(fù)試驗(yàn)比較不同的語(yǔ)句以得到最佳方案。最好的方法當(dāng)然是測(cè)試,看實(shí)現(xiàn)相同功能的SQL語(yǔ)句哪個(gè)執(zhí)行時(shí)間最少,但是數(shù)據(jù)庫(kù)中如果數(shù)據(jù)量很少,是比較不出來(lái)的,這時(shí)可以用查看執(zhí)行計(jì)劃,即:把實(shí)現(xiàn)相同功能的多條SQL語(yǔ)句考到查詢(xún)分析器,按CTRL+L看查所利用的索引,表掃描次數(shù)(這兩個(gè)對(duì)性能影響最大),總體上看詢(xún)成本百分比即可。

      看完上述內(nèi)容,你們掌握SQL Server數(shù)據(jù)庫(kù)sql優(yōu)化注意事項(xiàng)都有哪些的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!


      分享名稱(chēng):SQLServer數(shù)據(jù)庫(kù)sql優(yōu)化注意事項(xiàng)都有哪些
      分享地址:http://www.ef60e0e.cn/article/jigeii.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        项城市| 东阿县| 陇川县| 锡林郭勒盟| 兖州市| 山阳县| 邯郸市| 阿拉尔市| 屏山县| 靖安县| 长治市| 阿克陶县| 满城县| 云阳县| 通道| 甘洛县| 永靖县| 霍州市| 苍南县| 项城市| 德保县| 波密县| 祁连县| 内丘县| 观塘区| 石渠县| 泗水县| 玉树县| 张家界市| 安溪县| 泸定县| 江源县| 开鲁县| 额济纳旗| 宣威市| 喀什市| 佳木斯市| 公安县| 宜君县| 贺州市| 汝阳县|