1. 查看執行時間和cpusql
set statistics time on select * from Bus_DevHistoryData set statistics time off
執行後在消息裏能夠看到數據庫
2. 查看查詢對I/O的操做狀況編程
set statistics io on select * from Bus_DevHistoryData set statistics io off
執行以後的結果:緩存
掃描計數:索引和表執行次數安全
邏輯讀取:數據緩存中讀取的頁數性能優化
物理讀取:從磁盤中讀取的頁數服務器
預讀:查詢過程當中,從磁盤放入緩存的頁數網絡
lob邏輯讀取:從數據緩存中讀取image、text、ntext或大型數據的頁數併發
lob物理讀取:從磁盤中讀取image、text、ntext或大型數據的頁數app
lob預讀:查詢過程當中,從磁盤放入緩存的image、text、ntext或大型數據的頁數
若是物理讀取次數和預計次數比較多,可使用索引進行優化。
上述兩種信息的查看若是不想寫sql,能夠經過設置完成:
工具->選項
3. 查看執行計劃
選中查詢語句,點擊
1、數據庫設計優化
一、不要使用遊標。
使用遊標不只佔用內存,並且還用難以想象的方式鎖定表,它們可使DBA所能作的一切性能優化等於沒作。遊標裏每執行一次fetch就等於執行一次select。
二、建立適當的索引
每當爲一個表添加一個索引,select會更快,可insert和delete卻大大變慢,由於建立了維護索引須要許多額外的工做。
(1)採用函數處理的字段不能利用索引
(2)條件內包括了多個本表的字段運算時不能進行索引
三、使用事務
對於一些耗時的操做,使用事務能夠達到很好的優化效果。
四、當心死鎖
按照必定的次序來訪問你的表。若是你先鎖住表A,再鎖住表B,那麼在全部的存儲過程當中都要按照這個順序來鎖定它們。 若是某個存儲過程先鎖定表B,再鎖定表A,這可能會致使一個死鎖。
五、不要打開大的數據集
六、不要使用服務器端遊標
與服務器端遊標比起來,客戶端遊標能夠減小服務器和網絡的系統開銷,而且還減小鎖定時間。
七、不要忽略同時修改同一記錄的問題
有時候,兩個用戶會同時修改同一記錄,這樣,後一個修改者修改了前一個修改者的操做,某些更新就會丟失。處理這種狀況,建立一個timestamp字段,在寫入前檢查它,若是容許,就合併修改,若是存在衝突,提示用戶。
八、儘可能不要使用text數據類型
除非使用text處理一個很大的數據,不然不要使用它。由於它不易於查詢,速度慢,用的很差還會浪費大量的空間。通常varchar能夠更好的處理數據。
九、避免在索引列上使用計算
where子句中,若是索引列是函數的一部分,優化器將不使用索引而使用全表掃描。例如:
(低效)select ... from [dept] where [sal]*12>25000;
(高效)select ... from [dept] where [sal]>25000/12;
十、不一樣類型的索引效能是不同的,應儘量先使用效能高的
數字類型的索引查找效率高於字符串類型,定長字符串char、nchar的索引效率高於變長字符串varchar、nvarchar的索引。
(低效)select ... from tableName where username='張三' and age>=21
(高效)select ... from tableName where age>=21 and username='張三'
2、SQL語句優化
一、不要使用select *
在select中指定所須要的列,將帶來的好處:
(1)減小內存耗費和網絡的帶寬
(2)更安全
(3)給查詢優化器機會從索引讀取全部須要的列
二、使用參數查詢
主要是防止SQL注入,提升安全性。
三、使用exists或not exists代替in或not in
(高效)select * from [emp] where [empno]>0 and exists (select 'X' from [dept] where [dept].[deptno]=[emp].[deptno] and [loc]='MELB');
(低效)select * from [emp] where [empno]>0 and [deptno] in (select [deptno] from [dept] where [loc]='MELB');
四、is null或is not null操做
判斷字段是否爲空通常是不會應用索引的,由於索引不索引空值。不能用null做索引,任何包含null值的列都將不會被包含在索引中。也就是說若是某列存在空值,即便對該列建索引也不會提升性能。任何在where子句中使用is null或is not null的語句優化器都不容許使用索引。
推薦方案:用其餘相同功能的操做運算代替,如:a is not null改成a>0或a>''等。
五、<及>操做
大於或小於通常狀況不用調整,由於它有索引就會採用索引查找,但有的狀況下能夠對它進行優化。如一個表有100萬記錄,那麼執行>2與>=3的效果就有很大區別了。
(低效)select * from [emp] where [deptno]>2;
(高效)select * from [emp] where [deptno]>=3;
六、like操做
like操做能夠應用通配符查詢,裏面的通配符組合可能達到幾乎是任意的查詢,可是若是用很差則會產生性能上的問題,如lide '%5400%' 這種查詢不會引用索引,而like 'X5400%' 則會引用範圍索引。
七、where後面的條件順序影響
where子句後面的條件順序對大數據量表的查詢會產生直接的影響。如:
select * from zl_yhjbqk where dy_dj='1KV如下' and xh_bz=1;
select * from zl_yhjbqk where dy_dj=1 and dy_dj='1KV如下';
以上兩個查詢,兩個字段都沒進行索引,因此執行的時候都是全表掃描,第一條SQL的dy_dj='1KV如下'條件在記錄集內比率爲99%,而xh_bz=1的比率只爲0.5%,在進行第一條SQL的時候99%條記錄都進行dy_dj及xh_bz的比較。而在進行第二條SQL的時候0.5%條記錄都進行dy_dj及xh_bz的比較,以此能夠得出第二條SQL的CPU佔用率明顯比第一條低。
八、用union替換or(適用於索引列)
一般狀況下,用union替換where子句中的or將會起到較好的效果。對索引列使用or將形成全表掃描。注意:這個規則只針對多個索引列有效。若是有column沒有被索引,查詢效率可能會由於你沒有選擇or而下降。下面的例子中loc_id和region上都有建索引。
(低效)select loc_id,loc_desc,begion from location where loc_id=10 or begion='MELBOURNE';
(高效)select loc_id,loc_desc,begion from location where loc_id=10
union
select loc_id,loc_desc_begion from location where begion='MELBOURNE';
九、優化group by
提升group by語句的效率,能夠經過將不須要的記錄在group by以前過濾掉。
(低效)select [job],avg([sal]) from [emp] group by [job] having job='PRESIDENT' or job='MANAGER';
(高效)select [job],avg([sal]) from [emp] where [job]='PRESIDENT' or job='MANAGER' group by [job];
十、使用存儲過程
能夠考慮使用存儲過程封裝那些複雜的SQL語句或業務邏輯,這樣有幾個好處:
(1)存儲過程的執行計劃能夠被緩存在內存中較長的時間,減小了從新編譯的時間。
(2)存儲過程減小了客戶端和服務器的繁複交互。
(3)若是程序發佈後須要作某些改變你能夠直接修改存儲過程而不用修改程序,避免須要從新安裝部署程序。
十一、用sp_configure 'query governor cost limit'或者SET QUERY_GOVERNOR_COST_LIMIT來限制查詢消耗的資源。當評估查詢消耗的資源超出限制時,服務器自動取消查詢,在查詢以前就扼殺掉。SET LOCKTIME設置鎖的時間。
十二、使用select top或set rowcount來限制操做的行。
1三、若是使用了in或or等時發現查詢沒有走索引,使用顯式申明指定索引: SELECT * FROM PersonMember (INDEX = IX_Title) WHERE processid IN ('男','女')。
1四、若是要插入大的二進制值到Image列,使用存儲過程,千萬不要用內嵌insert來插入(不知JAVA是否)。由於這樣應用程序首先將二進制值轉換成字符串(尺寸是它的兩倍),服務器受到字符後又將他轉換成二進制值。存儲過程就沒有這些動做: 方法:Create procedure p_insert as insert into table(Fimage) values (@image), 在前臺調用這個存儲過程傳入二進制參數,這樣處理速度明顯改善。
1五、分析select emp_name form employee where salary>3000 在此語句中若salary是Float類型的,則優化器對其進行優化爲Convert(float,3000),由於3000是個整數,咱們應在編程時使用3000.0而不要等運行時讓DBMS進行轉化。一樣字符和整型數據的轉換。
3、處理百萬級以上數據提升查詢速度的方法
一、儘可能避免在where子句中使用!=或<>操做符,不然將使引擎放棄使用索引而進行全表掃描。
二、應考慮在where及order by涉及的列上創建索引。
三、儘可能避免在where子句中對字段進行null值判斷,不然將致使全表掃描。
四、就是避免在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
五、儘可能避免使用前置百分號。
select id from t where name like '%abc%'
六、in 和not in也要慎用,不少時候能夠用exists和not exists,不然會致使全表掃描。
七、若是在where子句中使用參數,也會致使全表掃描。
select id from t where num=@num 能夠改成強制查詢使用索引
select id from t with(index(索引名)) where num=@num
八、儘可能避免在where子句中對字段進行表達式操做,不然將致使全表掃描。
select id from t where num/2=100
應改成:
select id from t where num=100*2
九、儘可能避免在where子句中對字段進行函數操做,不然將致使全表掃描。
select id from t where substring(name,1,3)='abc'
應改成:
select id from t where name like 'abc%'
十、並非全部索引對查詢都有效,SQL根據表中數據來進行查詢優化,當索引列有大量數據重複時,SQL查詢可能不會去利用索引。
十一、索引並非越多越好,索引提交了select效率,可是下降了insert和update的效率。一個表的索引數最好不要超過6個。
十二、儘可能使用數字型字段,若只含數值信息的字段儘可能不要設計爲字符型,這會下降查詢和鏈接的性能,並會增長存儲開銷。由於引擎在處理查詢和鏈接時會逐個比較字符串中每一個字符,而對於數字型而言只須要比較一次就夠了。
1三、儘量使用varchar/nvarchar代替char/nchar,由於首先變長字段存儲空間小,能夠節省存儲空間;其次對於查詢來講,在一個相對較小的字段內搜索效率顯然要高些。
1四、任何地方都不要使用select *,用具體的字段列表代替*,不要返回用不到的字段。
1五、儘可能避免使用遊標,由於遊標的效率較差,若是遊標操做的數據超過1萬行,那麼就考慮改寫。
1六、儘可能避免大事務操做,提升系統併發能力。
1七、利用set rowcount實現高性能的分頁。
Declare @ID int Declare @MoveRecords int --@CurrentPage和@PageSize是傳入參數 Set @MoveRecords=@CurrentPage * @PageSize+1 --下面兩行實現快速滾動到咱們要取的數據的行,並把ID記錄下來 Set Rowcount @MoveRecords Select @ID=ID from Table1 Order by ID Set Rowcount @PageSize Select * From Table1 Where ID>=@ID Order By ID Set Rowcount 0
4、數據庫主鍵選取
常見的數據庫主鍵選取方式有:
●自動增加字段
●Uniqueidentifier
●「COMB(Combine)」類型
一、自動增加字段
優勢:
(1)簡單、效率高。
缺點:
(1)自增通常使用int型,有數據條數的限制。
(2)在數據庫進行數據合併時會比較麻煩。
二、GUID
優勢:
(1)安全,保證惟一性。
(2)不會產生自增字段那樣數據合併時的問題。
缺點:
(1)它的長度是16字節,佔用大量存儲空間。
(2)該數據類型毫無規律,要在上面創建索引很耗時,因此效率要比使用自增字段低。
三、COMB
考慮到上面兩種主鍵類型的優缺點,這裏使用COMB類型能夠爲二者找到了一個平衡點。它的設計思路是這樣的:既然GUID類型無規律可言形成索引效率低下,影響系統的性能,那麼能不能經過組合的方式,保留GUID前10個字節,用後6個字節表示GUID生成的時間,這樣即保證了惟一性同時增長了有序性,以此來提升索引效率。後6字節的時間精度能夠達到1/300秒,兩個COMB類型數據徹底相同的可能性是在這1/300秒內生成的兩個GUID前10個字節徹底相同,這幾乎是不可能的。
(1)SQL Server中SQL命令實現這一思路的方式: