T-sql腳本級別優化

一律述

sql語句的運行時間通常會主要花在3步:語句編譯,語句執行,結果集返回.sql

結果集返回的速度通常和sql server 自身沒有太大關係,因此通常不會在語句調優的時候考慮。 因此語句調優時,focus在於編譯和語句執行各花了多少時間,哪一段時間有優化空間,以及怎麼優化
數據庫


二常見優化套路

1 表關聯的時候 最好縮小範圍以後再關聯,這樣耗費內存少。
2 條件都出在一張表,爲何不把刷選都作掉,再join呢?——這樣join的數據集小,
3 搜索條件多的,能夠考慮使用動態sql——考慮根據是否傳參,拼接where條件以及join表——case when
4 order by 排序,表關聯on——考慮索引
5 儘可能不用視圖,啓用物理表,表關聯的時候 最好縮小範圍以後再關聯,這樣耗費內存少。
6 單表——索引
7 多表——join 順序,關聯條件加索引,儘可能不要join視圖複製代碼

三 優化指北

1 索引   待續:《索引的本質》 《數據庫內部存儲》bash

業務系統大多數時間基本上是排序和查找。索引=隱式排序+有序查找
缺點:索引建太多的話,會佔存儲空間。索引越多統計信息越多。寫入會變慢。複製代碼

2 事務與隔離級別   待續 :《事務與隔離級別》性能

1 READ_COMMITTED_SNAPSHOT隔離級別 能夠解決讀寫互斥
缺點:一次update,tempdb存一份以前的數據,這是update的性能取決於tempdb的IO。若是tempdb在一個爛磁盤上,那麼就涼涼了
2 with nolock: 是一種不請求鎖的機制。
缺點: 查詢有髒數據。不過呢,若是不care髒數據,可使用。複製代碼

3 T-sql 存儲過程化優化

減小重編譯
遇到邏輯修改,直接修改db,不須要程序再次發佈,節約人力和時間雙重成本複製代碼

4 科學設計表結構, 表結構是根本.ui

一個好的表結構:
1 避免數據傾斜,進而避免參數嗅探
2 後期易n次迭代開發
3 易維護與優化複製代碼

5 適當反範式 
spa

咱們遵照數據庫第三範式的同時,應該考慮適當反範式,減小過多的表關聯複製代碼

6 熱點表的優待設計

1 熱點表應放在吞吐好的磁盤
2 同時設置文件組,將數據文件分配到不一樣磁盤,以免IO瓶頸複製代碼

7 tempdb的優待     待續《tempdb的做用》code

同理,tempdb數據庫也應該放在性能好的磁盤,避免tempdb文件頭爭用複製代碼

四例子

經典查詢:分頁server

1 多條件搜索,應該使用動態sql。拼接sql
2 使用動態sql 須要注意:sql注入
3 根據參數是否傳入,拼接join表,以及where條件——應使用case when 應付多變性

CREATE PROC [dbo].[SP_GET_Person] 
@ZoneID INT=NULL,
@Name VARCHAR(50)=NULL,
@RoomNo VARCHAR(50)=NULL,
@StartNum INT=0,
@EndNum INT=10

AS
BEGIN 
  DECLARE @Sql NVARCHAR(MAX); 
  DECLARE @Sql_TotalCount NVARCHAR(MAX); --檢索返回的總數
  DECLARE @Sql_Paged NVARCHAR(MAX); --分頁
  DECLARE @Sql_Common NVARCHAR(MAX);--總數和分頁邏輯相同的sql腳本(表join和where條件)
  -----總數-----
  SET @Sql_TotalCount=N' DECLARE @TotalCount INT; SELECT @TotalCount=COUNT(*)'

  SET @Sql_Common=N' FROM [dbo].[EST_House] HH'
  
  +CASE WHEN @ZoneID IS NOT NULL OR @Name IS NOT NULL
  THEN ' JOIN [dbo].[EEEE] E ON HH.ID=E.ID'
  ELSE '' END

  +CASE WHEN @ZoneID IS NOT NULL THEN
  'JOIN [dbo].[Zone] K ON E.ZoneID=K.ZoneID'
  ELSE '' END

  +' WHERE HH.IsDelete = 0 AND HH.IsRecycleBin = 0'
  
  +CASE WHEN @ZoneID IS NOT NULL THEN
  ' AND K.ZoneID =@VAR_ZoneID'
  ELSE '' END 
  +CASE WHEN @Name IS NOT NULL THEN
  ' AND E.Name LIKE ''%''+@VAR_Name+''%'''
  ELSE '' END
  +CASE WHEN @RoomNo IS NOT NULL THEN
  ' AND HH.RoomNo LIKE ''%''+@VAR_RoomNo+''%'''
  ELSE '' END
  
  -----分頁-----
  SET @Sql_Paged=N' SELECT TOP(@VAR_EndNum) RowNumber=row_number() OVER (ORDER BY HH.updatetime DESC) ,HH.[House] INTO #Temp1 '+@Sql_Common+N' SELECT * INTO #Temp2 FROM #Temp1 WHERE RowNumber>=@VAR_StartNum; SELECT TotalCount=@TotalCount ,RowNumber ,E.[ZoneID] ,K.[ZoneName] ,E.[Name] ,B.[BuildingName] ,HH.[RoomNo] FROM #Temp2 H JOIN [dbo].[House] HH ON H.[HouseID]=HH.[HouseID] JOIN [dbo].[EEEE] E ON HH.EID=E.EID JOIN [dbo].[Zone] K ON E.ZoneID=K.ZoneID ORDER BY H.RowNumber; '
  SET @Sql=@Sql_TotalCount+@Sql_Common+@Sql_Paged

  PRINT @Sql

 
  EXEC SP_EXECUTESQL @Sql,
  N' @VAR_ZoneID INT, @VAR_Name VARCHAR(50), @VAR_RoomNo VARCHAR(50), @VAR_StartNum INT, @VAR_EndNum INT',

  @VAR_ZoneID=@ZoneID,
  @VAR_Name=@Name,
  @VAR_RoomNo=@RoomNo,
  @VAR_StartNum=@StartNum,
  @VAR_EndNum=@EndNum


END














GO複製代碼
相關文章
相關標籤/搜索