SQL Server數據庫性能優化


  開篇:   

    最近遇到了很多性能問題,一直沒來的及總結,今天正好周末抽時間總結下:

    對於稍微大點的公司或者說用戶多一些的公司,說白了就是數據量較大的公司,在查詢數據時往往會遇到很多瓶頸。這時就需要性能優化。  性能優化分為代碼優化和數據庫優化,常見的代碼優化有分頁查詢,with(nolock)使用無鎖模式。  數據庫優化主要是創建索引。 

  一個苦逼的事情是我們的老系統沒有使用分頁查詢,而是通過查詢出所有的數據然后利用前台控件進行的分頁。(PS:一個合格的架構師需要不斷學習前沿技術,而不是固步自封,設計出垃圾架構)。所以系統經常提示連接數據庫超時。。。  所以要解決這個問題我們只能從數據庫優化下手。 

   因為此文要圍繞索引展開,所以在開始之前先了解幾個概念,及什么是索引? 什么是聚集索引,什么是非聚集索引?什么是主鍵? 建立非聚集索引時,索引鍵列和包含性列分別指的什么?

   什么是索引?舉個例子你就明白了,索引就相當於字典目錄,根據目錄查找你想要找的文字。如果沒有目錄的話,你就得一頁一頁的翻,看哪個文字是自己想要的。所以我們要建立索引。

   什么是聚集索引,什么是非聚集索引?一張表里面可以有多個非聚集索引,但只能有一個聚集索引。數據會按照聚集索引進行物理排序,聚集索引和數據是綁定在一起的。而非聚集索引是數據和索引位置分開的,索引上有個指針指向數據。還是拿字典舉例,聚集索引就相當於你通過拼音查找,他是有順序的,A,B,C...是依次排列的,你可以通過拼音直接找到文字位置。而非聚集索引就相當於通過偏旁查找,你先要找到偏旁,然后根據偏旁查找文字,最后才知道在哪一頁。 搞不懂的話,可以看下這個 。

   什么是主鍵?  主鍵主要是確定資料的唯一性。設置主鍵的字段(可多個字段一起做主鍵)。例如人事資料中有一個身份證號的字段。這個就可設為主鍵(因為身份證號不會重復).但姓名就不可以,因為姓名可以重復,另外設置了主鍵有利於提高數據的檢索速度.也保證數據准確性。 主鍵和索引沒有什么必然聯系,主鍵是確定唯一性的,索引是排序用的。

    建立非聚集索引時,索引鍵列和包含性列分別指的什么?  首先聲明下,建立非聚集索引的前提是有where查詢條件或者order by時建立才有意義。 索引鍵列一般選取的就是根據where要查詢的字段。包含性列是要查詢的字段。包含性列是對查詢條件的一種性能補充。 可能說的不是很明白,詳細可以參考:https://www.cnblogs.com/sc0791/p/3720249.html

 

  正文:

  首先先創建Grade和Member兩個數據庫表並插入數據來進行模擬,創建數據庫腳本如下:  

create table Grade(
ID int primary key identity,
MathGrade int null,
ChineseGrade int null,
EnglishGrade int null,
MemberID int null,
CreateTime DateTime
)

create table Member(
ID int primary key identity,
MemberName nvarchar(20)
)

--在Grade里面循環插入數據
Declare @I int
Set @I=0
Begin Tran
InsertData:
Insert into Grade values(@I,@I+10,@I+20,@I+30,GETDATE())
Set @I=@I+1
if @I<100000
Goto InsertData
Commit Tran

--在Member里面循環插入數據
Declare @I int
Set @I=0
Begin Tran
InsertData:
Insert into Member values('姓名'+Convert(nvarchar(20), @I))
Set @I=@I+1
if @I<100000
Goto InsertData
Commit Tran

 OK,Grade表和Member表都創建好了,並都插入了10W條數據。Grade表中的MemberID和Member表ID是一一對應關系。下面開始測試性能。

執行代碼:

declare @begin_date datetime 
declare @end_date datetime 
select @begin_date = getdate() 

select g.ID,g.MathGrade,m.MemberName,g.CreateTime from Grade g
left join Member m
on g.MemberID=m.ID
order by g.CreateTime

select @end_date = getdate() 
select datediff(ms,@begin_date,@end_date) as '用時/毫秒' 

OK,下面開始優化,少於1930毫秒則證明優化成功~

選擇 工具->數據庫引擎優化顧問

或者右鍵空白處選擇 在數據庫引擎優化顧問中分析查詢

 

 應用后再次執行,如下圖:

先不用管它,先看下上面執行了什么,如下圖:

從上面可以看到,它把我們的查詢條件都包含進了非聚集索引里面。  emmm~下面看下有沒有命中索引:

 

 SQL Server有幾種方式查找數據記錄:

[Table Scan]表掃描(最慢),這種情況是沒索引的前提下。

[Clustered Index Scan]聚集索引掃描(較慢) ,這種情況是只有主鍵索引的前提下。

[Index Scan]索引掃描(普通),這種情況是有主鍵索引,並且要搜索的數據建立了非聚集索引的前提下。

[Index Seek]索引查找(較快),這種情況是where條件里面沒有根據主鍵進行過濾時,把過濾的字段加在索引鍵列上,其余加在包含列上的前提下。

[Clustered Index Seek]聚集索引查找(最快)。這種情況是根據主鍵進行where過濾的前提下。

這塊具體實例我就不演示了,想看的話參考:https://www.cnblogs.com/taiyonghai/p/5594826.html

----休息一下!!!

來,繼續!!!上面主要是通過工具生成優化腳本,我們還可以通過圖形化工具自己定義,同時還可以寫腳本創建。

如下圖:(圖形化工具創建兩張圖完美解釋)

 腳本創建如下:

 

CREATE [索引類型] INDEX 索引名稱
ON 表名(列名)
WITH FILLFACTOR = 填充因子值0~100
GO

 

索引類型有:

-- 聚集索引(Clustered)
-- 非聚集索引(NonClustered)

填充因子解釋:http://blog.csdn.net/silentmuh/article/details/50403228

創建聚集索引時,因為有時要創建包含性列,比較特殊,所以舉個例子:

create NonClustered index SuoYiin_Name on ActionInfo(ControllerName,ParID) include
(ActionID) WITH FILLFACTOR = 80  
 --這樣就給ActionInfo表中的ControllerName和ParID創建了一個包含ActionID的非聚集索引

 

好啦,數據庫優化就這么多啦,細節比較多,但是學會的話還是感覺挺簡單的,快去動手試試吧~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM