SQL脚本优化
1.創建索引
一.要盡量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引
? (1)在經常需要進行檢索的字段上創建索引,比如要按照表字段username進行檢索,那么就應該在姓名字段上創建索引,如果經常要按照員工部門和員工崗位級別進行檢索,那么就應該在員工部門和員工崗位級別這兩個字段上創建索引。
? (2)創建索引給檢索帶來的性能提升往往是巨大的,因此在發現檢索速度過慢的時候應該首先想到的就是創建索引。
? (3)一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有 必要。索引并不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,因為 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。
2.避免在索引上使用計算
在where字句中,如果索引列是計算或者函數的一部分,DBMS的優化器將不會使用索引而使用全表查詢,函數
屬于計算的一種,同時在in和exists中通常情況下使用EXISTS,因為in不走索引
效率低:
?select * from user where salary*22>11000(salary是索引列)
效率高:
?select * from user where salary>11000/22(salary是索引列)
?
如果where語句中有多個字段,那么可以考慮創建組合索引。
組合索引中字段的順序是非常重要的,越是唯一的字段越是要靠前。
另外,無論是組合索引還是單個列的索引,盡量不要選擇那些唯一性很低的字段。
比如說,在只有兩個值0和1的字段上建立索引沒有多大意義。
3.調整Where字句中的連接順序
ORACLE 采用自下而上的順序解析WHERE 子句,根據這個原理,表之間的連接必須寫在其他
WHERE 條件之前, 那些可以過濾掉最大數量記錄的條件必須寫在WHERE 子句的末尾.
4.用union all替換union
當SQL語句需要union兩個查詢結果集合時,即使檢索結果中不會有重復的記錄,如果使用union這兩個結果集
同樣會嘗試進行合并,然后在輸出最終結果前進行排序,因此如果可以判斷檢索結果中不會有重復的記錄時候,應
該用union all,這樣效率就會因此得到提高。
5.考慮使用“臨時表”暫存中間結果
簡化SQL語句的重要方法就是采用臨時表暫存中間結果,但是,臨時表的好處遠遠不止這些,將臨時結果暫存在臨時表,后面的查詢就在tempdb中了,這可以避免程序中多次掃描主表,也大大減少了程序執行中“共享鎖”阻塞“更新鎖”,減少了阻塞,提高了并發性能。
但是也得避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。
6.限制結果集
要盡量減少返回的結果行,包括行數和字段列數,只提取必須要的字段
返回的結果越大,意味著相應的SQL語句的logical reads 就越大,對服務器的性能影響就越甚。
一個很不好的設計就是返回表的所有數據
7.應盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。
8.對查詢進行優化,應盡量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。
9.應盡量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
???? select id from t where num is null
???? 可以在num上設置默認值0,確保表中num列沒有null值,然后這樣查詢:
???? select id from t where num=0
??? ?
??? ?
10.應盡量避免在 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
11.下面的查詢也將導致全表掃描:(不能前置百分號)
???? select id from t where name like ‘%abc%’
??? 若要提高效率,可以考慮全文檢索。
12.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
??? ?
13.應盡量避免在 where 子句中對字段進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
???? select id from t where num/2=100
???? 應改為:
???? select id from t where num=100*2
??? ?
14.應盡量避免在where子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:
???? select id from t where substring(name,1,3)=’abc’–name以abc開頭的id
???? select id from t where datediff(day,createdate,’2005-11-30′)=0–’2005-11-30′生成的id
???? 應改為:
???? select id from t where name like ‘abc%’
???? select id from t where createdate >= ’2005-11-30′ and createdate < ’2005-12-1′
??? ?
??? ?
15.不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。
16.很多時候用 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)
轉載于:https://www.cnblogs.com/hello-wei/p/11060131.html
總結
- 上一篇: sql语句列名为变量(Spring Bo
- 下一篇: 关于MongoDB数据库的总结