避免全表掃瞄的sql優化

2021-08-07 07:54:50 字數 3425 閱讀 5158

/**

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

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

· 使用analyze

table tbl_name為掃瞄的表更新關鍵字分布。

· 對掃瞄的表使用force

index告知mysql,相對於使用給定的索引表掃瞄將非常耗時。

select * from t1, t2 force

index (index_for_column)

where t1.col_name=t2.col_name;

· 用--max-seeks-for-key=1000選項啟動mysqld或使用set max_seeks_for_key=1000告知優化器假設關鍵字掃瞄不會超過1,000次關鍵字搜尋。

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

如:select

idfrom t where

numis

null

null對於大多數資料庫都需要特殊處理,mysql也不例外,它需要更多的**,更多的檢查和特殊的索引邏輯,有些開發人員完全沒有意識到,建立表時null是預設值,但大多數時候應該使用not

null,或者使用乙個特殊的值,如0,-1作為默 認值。

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

null或is

notnull的語句優化器是不允許使用索引的。

此例可以在num上設定預設值0,確保表中num列沒有null值,然後這樣查詢:

select

idfrom t where

num=0

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

mysql只有對以下操作符才使用索引:<,<=,=,>,>=,between,in,以及某些時候的like。 可以在like操作中使用索引的情形是指另乙個運算元不是以萬用字元(%或者_)開頭的情形。例如,「select

idfrom t where

collike

'mich%';」這個查詢將使用索引,但「select

idfrom t where

collike

'%ike';」這個查詢不會使用索引。

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

如:select

idfrom t where

num=10

ornum=20

可以這樣查詢:select

idfrom t where

num=10

union all select

idfrom t where

num=20

4 .in 和not

in 也要慎用,否則會導致全表掃瞄,

如:select

idfrom t where

numin(1,2,3)

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

select

idfrom t where

numbetween

1and

35.下面的查詢也將導致全表掃瞄:

select

idfrom t where

name

like

'%abc%' 或者

select

idfrom t where

name

like

'%abc' 或者

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

而select

idfrom t where

name

like

'abc%' 才用到索引

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

select

idfrom t where

num=@num

可以改為強制查詢使用索引:select

idfrom t with(index(索引名)) where

num=@num

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

如:select

idfrom t where

num/2=100

應改為: select

idfrom t where

num=100*2

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

select

idfrom t where

substring(name,1,3)='abc'

--name

select

idfrom t where

datediff(day,createdate,'2005-11-30')=0

--『2005-11-30』生成的id 應改為:

select

idfrom t where

name

like

'abc%'

select

idfrom t where createdate>='2005-11-30'

and createdate<'2005-12-1'

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

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

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

select

numfrom a where

numin(select

numfrom b)

用下面的語句替換:

select

numfrom a where

exists(select

1from b where

num=a.num)

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

避免全表掃瞄的sql優化

26.使用基於游標的方法或臨時表方法之前,應先尋找基於集的解決方案來解決問題,基於集的方法通常更有效。27.與臨時表一樣,游標並不是不可使用。對小型資料集使用fast forward 游標通常要優於其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的資料時。在結果集中包括 合計 的例程通常要比使用...

避免全表掃瞄

在應用的程式設計中,除了一些必要的情況下,如月報資料的統計。列印所有清單等可以允許使用全表掃瞄外,一般都盡量避免涉及全表掃瞄。全表掃瞄就是指不加任何條件的查詢語句。下面情況可以 oracle 就使用全表掃瞄 1 所查詢的表沒有索引 2 需要返回所有的行 3 對索引主列有條件限制,但是使用了函式,則 ...

mysql 避免全表 mysql避免全表掃瞄

我們在寫資料庫查詢語句的時候,經常會忽略一些查詢效能問題,導致最後在查詢資料的情況下非常耗時,影響專案質量。資料庫的設計是一門藝術,需要遵循一定的規範。對資料量很大的表一定要建立合適的索引,無論是單個索引還是復合索引,要根據查詢的業務邏輯去建立,同時也記住,單個表的索參數量不得超過5個,不然會很導致...