久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

如何避免全表掃描的sql優化

125次閱讀
沒有評論

共計 3990 個字符,預計需要花費 10 分鐘才能閱讀完成。

這期內容當中丸趣 TV 小編將會給大家帶來有關如何避免全表掃描的 sql 優化,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

對查詢進行優化,應盡量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引:

 . 嘗試下面的技巧以避免優化器錯選了表掃描:

middot;    使用 ANALYZE TABLE tbl_name 為掃描的表更新關鍵字分布。

middot;    對掃描的表使用 FORCE INDEX 告知 MySQL,相對于使用給定的索引表掃描將非常耗時。

           SELECT * FROM t1, t2 FORCE INDEX (index_for_column)

            WHERE t1.col_name=t2.col_name;

middot;    用 –max-seeks-for-key=1000 選項啟動 mysqld 或使用 SET max_seeks_for_key=1000 告知優化器假設關鍵字掃描不會超過 1,000 次關鍵字搜索。

 1. 應盡量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,

      如:

      select id from t where num is null

     NULL 對于大多數都需要特殊處理,MySQL 也不例外,它需要更多的代碼,更多的檢查和特殊的索引邏輯,有些開發人員完全沒有意識到,創建表時 NULL 是默認值,但大多數時候應該使用 NOT NULL,或者使用一個特殊的值,如 0,- 1 作為默   認值。

      不能用 null 作索引,任何包含 null 值的列都將不會被包含在索引中。即使索引有多列這樣的情況下,只要這些列中有一列含有 null,該列     就會從索引中排除。也就是說如果某列存在空值,即使對該列建索引也不會提高性能。任何在 where 子句中使用 is null 或 is not null 的語句優化器是不允許使用索引的。

      此例可以在 num 上設置默認值 0,確保表中 num 列沒有 null 值,然后這樣查詢:

      select id    from t where num=0

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

   MySQL 只有對以下操作符才使用索引:,=,=,,=,BETWEEN,IN,以及某些時候的 LIKE。可以在 LIKE 操作中使用索引的情形是指另一個操作數不是以通配符(% 或者_)開頭的情形。例如,“SELECT id FROM t WHERE col LIKE Mich%”這個查詢將使用索引,但“SELECT id FROM t WHERE col  LIKE %ike”這個查詢不會使用索引。

 3. 應盡量避免在 where 子句中使用 or 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描,

    如:

    select id from t where num=10 or num=20

    可以這樣查詢:select id from t where num=10 union all select id from t where num=20

 4 .in 和 not in 也要慎用,否則會導致全表掃描,

    如:

   select id from t where num in(1,2,3)

    對于連續的數值,能用 between 就不要用 in 了:

   select id from t where num between 1 and 3

  5. 下面的查詢也將導致全表掃描:

       select id from t where name like %abc% 或者

       select id from t where name like %abc 或者

        若要提高效率,可以考慮全文檢索。

      而 select id from t where name like abc% 才用到索引

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

    select id from t where num=@num

    可以改為強制查詢使用索引:select id from t with(index( 索引名)) where num=@num

 8. 應盡量避免在 where 子句中對字段進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。

  如:

  select id from t where num/2=100

應改為:

 select id from t where num=100*2

9. 應盡量避免在 where 子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。

如:

select id from t where substring(name,1,3)= abc –name

select id from t where datediff(day,createdate, 2005-11-30)=0– lsquo;2005-11-30 rsquo; 生成的 id 應改為:

select id from t where name like abc%

select id from t where createdate = 2005-11-30 and createdate 2005-12-1

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

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

12. 不要寫一些沒有意義的查詢,

如需要生成一個空表結構:

 select col1,col2 into #t from t where 1=0

這類代碼不會返回任何結果集,但是會消耗系統資源的,應改成這樣:create table #t(…)

13. 很多時候用 exists 代替 in 是一個好的選擇:

select num from a where num in(select num from b)

用下面的語句替換:

select num from a where exists(select 1 from b where num=a.num)

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

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

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

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

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

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

20. 盡量使用表變量來代替臨時表。如果表變量包含大量數據,請注意索引非常有限(只有主鍵索引)。21. 避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。

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

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

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

25. 盡量避免使用游標,因為游標的效率較差,如果游標操作的數據超過 1 萬行,那么就應該考慮改寫。26. 使用基于游標的方法或臨時表方法之前,應先尋找基于集的解決方案來解決問題,基于集的方法通常更有效。

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

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

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

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

上述就是丸趣 TV 小編為大家分享的如何避免全表掃描的 sql 優化了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注丸趣 TV 行業資訊頻道。

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-07-19發表,共計3990字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 酒泉市| 峨山| 老河口市| 利津县| 潮安县| 郓城县| 彩票| 宁晋县| 台东县| 当雄县| 蒙山县| 济阳县| 肥东县| 沿河| 临泽县| 惠州市| 二手房| 合水县| 饶河县| 甘谷县| 建平县| 北碚区| 康乐县| 门头沟区| 南靖县| 聂拉木县| 海南省| 噶尔县| 西青区| 综艺| 海原县| 恩平市| 蕲春县| 常德市| 佛山市| 晋江市| 铁岭县| 高雄市| 宜兰市| 耒阳市| 颍上县|