1.應盡量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:x0dx0aselect id from t where num is nullx0dx0a可以在num上設置默認值0,確保表中num列沒有null值,然後這樣查詢:x0dx0aselect id from t where num=0x0dx0a2.應盡量避免在 where 子句顫洞中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。優化器將無法通過索引來確定將要命中的行數,因此需要搜索該表的所有行。x0dx0a3.應盡量避免在 where 子句中使用 or 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描,如:x0dx0aselect id from t where num=10 or num=20x0dx0a可以這樣查詢:x0dx0aselect id from t where num=10x0dx0aunion allx0dx0aselect id from t where num=20x0dx0a4.in 和 not in 也要慎用,因為IN會使系統無法使用索引,而只能直接搜索表中的數據。如:x0dx0aselect id from t where num in(1,2,3)x0dx0a對於連續的數值,能用 between 就不要用 in 了:x0dx0aselect id from t where num between 1 and 3x0dx0a5.盡量避免在索引過的字元數據中,使用非打頭字母搜索。這也使得引擎無法利用索引。 x0dx0a見如下例子: x0dx0aSELECT * FROM T1 WHERE NAME LIKE 『%L%』 x0dx0aSELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=』L』 x0dx0aSELECT * FROM T1 WHERE NAME LIKE 『L%』 x0dx0a即使NAME欄位建有索引,前兩個查詢依然無法利用春嘩索引完成加快操作,引擎不得不對全表所有數據逐條操作來完成任務。而第三個查詢能夠使用索引來加快操作。x0dx0a6.必要時強制查詢優化器使用某個索引,如在 where 子句中使用參數,也會導致全表掃描。因為SQL只有在運行時才會解析局部變數,但優化程序不能將訪問計劃的選擇推遲到運行時;它必須在編譯時進行選擇。然而,如果在編譯時建立訪問計劃,變數的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:x0dx0aselect id from t where num=@numx0dx0a可以改為強制查詢使用索引:x0dx0aselect id from t with(index(索引名)) where num=@numx0dx0a7.應盡量避免在 where 子句中對欄位進行表達式操扒洞行作,這將導致引擎放棄使用索引而進行全表掃描。如:x0dx0aSELECT * FROM T1 WHERE F1/2=100 x0dx0a應改為: x0dx0aSELECT * FROM T1 WHERE F1=100*2x0dx0aSELECT * FROM RECORD WHERE SUBSTRING(CARD_NO,1,4)=』5378』 x0dx0a應改為: x0dx0aSELECT * FROM RECORD WHERE CARD_NO LIKE 『5378%』x0dx0aSELECT member_number, first_name, last_name FROM members x0dx0aWHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21 x0dx0a應改為: x0dx0aSELECT member_number, first_name, last_name FROM members x0dx0aWHERE dateofbirth < DATEADD(yy,-21,GETDATE()) x0dx0a即:任何對列的操作都將導致表掃描,它包括資料庫函數、計算表達式等等,查詢時要盡可能將操作移至等號右邊。x0dx0a8.應盡量避免在where子句中對欄位進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:x0dx0aselect id from t where substring(name,1,3)='abc'--name以abc開頭的idx0dx0aselect id from t where datediff(day,createdate,-11-30')=0--『2005-11-30』生成的idx0dx0a應改為:x0dx0aselect id from t where name like 'abc%'x0dx0aselect id from t where createdate>=-11-30' and createdate<-12-1'x0dx0a9.不要在 where 子句中的「=」左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。x0dx0a10.在使用索引欄位作為條件時,如果該索引是復合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應盡可能的讓欄位順序與索引順序相一致。x0dx0a11.很多時候用 exists是一個好的選擇:x0dx0aelect num from a where num in(select num from b)x0dx0a用下面的語句替換:x0dx0aselect num from a where exists(select 1 from b where num=a.num)x0dx0aSELECT SUM(T1.C1)FROM T1 WHERE( x0dx0a(SELECT COUNT(*)FROM T2 WHERE T2.C2=T1.C2>0) x0dx0aSELECT SUM(T1.C1) FROM T1WHERE EXISTS( x0dx0aSELECT * FROM T2 WHERE T2.C2=T1.C2) x0dx0a兩者產生相同的結果,但是後者的效率顯然要高於前者。因為後者不會產生大量鎖定的表掃描或是索引掃描。