第九步:合理組織數據庫文件組和文件數據庫
建立SQL Server數據庫時,數據庫服務器會自動在文件系統上建立一系列的文件,以後建立的每個數據庫對象實際上都是存儲在這些文件中的。SQL Server有下面三種文件:瀏覽器
1).mdf文件服務器
這是最主要的數據文件,每一個數據庫只能有一個主數據文件,全部系統對象都存儲在主數據文件中,若是不建立次要數據文件,全部用戶對象(用戶建立的數據庫對象)也都存儲在主數據文件中。併發
2).ndf文件編輯器
這些都是次要數據文件,它們是可選的,它們存儲的都是用戶建立的對象。分佈式
3).ldf文件函數
這些是事務日誌文件,數量從一到幾個不等,它裏面存儲的是事務日誌。高併發
默認狀況下,建立SQL Server數據庫時會自動建立主數據文件和事務日誌文件,固然也能夠修改這兩個文件的屬性,如保存路徑。性能
文件組優化
爲了便於管理和得到更好的性能,數據文件一般都進行了合理的分組,建立一個新的SQL Server數據庫時,會自動建立主文件組,主數據文件就包含在主文件組中,主文件組也被設爲默認組,所以全部新建立的用戶對象都自動存儲在主文件組中(具體說就是存儲在主數據文件中)。
若是你想將你的用戶對象(表、視圖、存儲過程和函數等)存儲在次要數據文件中,那須要:
1)建立一個新的文件組,並將其設爲默認文件組;
2)建立一個新的數據文件(.ndf),將其歸於第一步建立的新文件組中。
之後建立的對象就會所有存儲在次要文件組中了。
注意:事務日誌文件不屬於任何文件組。
文件/文件組組織最佳實踐
若是你的數據庫不大,那麼默認的文件/文件組應該就能知足你的須要,但若是你的數據庫變得很大時(假設有1000MB),你能夠(應該)對文件/文件組進行調整以得到更好的性能,調整文件/文件組的最佳實踐內容以下:
1)主文件組必須徹底獨立,它裏面應該只存儲系統對象,全部的用戶對象都不該該放在主文件組中。主文件組也不該該設爲默認組,將系統對象和用戶對象分開能夠得到更好的性能;
2)若是有多塊硬盤,能夠將每一個文件組中的每一個文件分配到每塊硬盤上,這樣能夠實現分佈式磁盤I/O,大大提升數據讀寫速度;
3)將訪問頻繁的表及其索引放到一個單獨的文件組中,這樣讀取表數據和索引都會更快;
4)將訪問頻繁的包含Text和Image數據類型的列的表放到一個單獨的文件組中,最好將其中的Text和Image列數據放在一個獨立的硬盤中,這樣檢索該表的非Text和Image列時速度就不會受Text和Image列的影響;
5)將事務日誌文件放在一個獨立的硬盤上,千萬不要和數據文件共用一塊硬盤,日誌操做屬於寫密集型操做,所以保證日誌寫入具備良好的I/O性能很是重要;
6)將「只讀」表單獨放到一個獨立的文件組中,一樣,將「只寫」表單獨放到一個文件組中,這樣只讀表的檢索速度會更快,只寫表的更新速度也會更快;
7)不要過分使用SQL Server的「自動增加」特性,由於自動增加的成本實際上是很高的,設置「自動增加」值爲一個合適的值,如一週,一樣,也不要過分頻繁地使用「自動收縮」特性,最好禁用掉自動收縮,改成手工收縮數據庫大小,或使用調度操做,設置一個合理的時間間隔,如一個月。
第十步:在大表上應用分區
什麼是表分區?
表分區就是將大表拆分紅多個小表,以避免檢索數據時掃描的數據太多,這個思想參考了「分而治之」的理論。
當你的數據庫中有一個大表(假設有上百萬行記錄),若是其它優化技巧都用上了,但查詢速度仍然很是慢時,你就應該考慮對這個表進行分區了。首先來看一下分區的類型:
水平分區:假設有一個表包括千萬行記錄,爲了便於理解,假設表有一個自動增加的主鍵字段(如id),咱們能夠將表拆分紅10個獨立的分區表,每一個分區包含100萬行記錄,分區就要依據id字段的值實施,即第一個分區包含id值從1-1000000的記錄,第二個分區包含1000001-2000000的記錄,以此類推。這種以水平方向分割表的方式就叫作水平分區。
垂直分區:假設有一個表的列數和行數都很是多,其中某些列被常常訪問,其他的列不是常常訪問。因爲表很是大,全部檢索操做都很慢,所以須要基於頻繁訪問的列進行分區,這樣咱們能夠將這個大表拆分紅多個小表,每一個小表由大表的一部分列組成,這種垂直拆分表的方法就叫作垂直分區。
另外一個垂直分區的原則是按有索引的列無索引列進行拆分,但這種分區法須要當心,由於若是任何查詢都涉及到檢索這兩個分區,SQL引擎不得不鏈接這兩個分區,那樣的話性能反而會低。
本文主要對水平分區作一介紹。
分區最佳實踐
1)將大表分區後,將每一個分區放在一個獨立的文件中,並將這個文件存放在獨立的硬盤上,這樣數據庫引擎能夠同時並行檢索多塊硬盤上的不一樣數據文件,提升併發讀寫速度;
2)對於歷史數據,能夠考慮基於歷史數據的「年齡」進行分區,例如,假設表中存儲的是訂單數據,可使用訂單日期列做爲分區的依據,如將每一年的訂單數據作成一個分區。
如何分區?
假設Order表中包含了四年(1999-2002)的訂單數據,有上百萬的記錄,那若是要對這個表進行分區,採起的步驟以下:
1)添加文件組
使用下面的命令建立一個文件組:
ALTER DATABASE OrderDB ADD FILEGROUP [1999]
ALTER DATABASE OrderDB ADD FILE (NAME = N'1999', FILENAME
= N'C:\OrderDB\1999.ndf', SIZE = 5MB, MAXSIZE = 100MB, FILEGROWTH = 5MB) TO
FILEGROUP [1999]
經過上面的語句咱們添加了一個文件組1999,而後增長了一個次要數據文件「C:\OrderDB\1999.ndf」到這個文件組中。
使用上面的命令再建立三個文件組2000,2001和2002,每一個文件組存儲一年的銷售數據。
2)建立分區函數
分區函數是定義分界點的一個對象,使用下面的命令建立分區函數:
CREATE PARTITION FUNCTION FNOrderDateRange (DateTime) AS
RANGE LEFT FOR VALUES ('19991231', '20001231', '20011231')
上面的分區函數指定:
DateTime<=1999/12/31的記錄進入第一個分區;
DateTime > 1999/12/31 且 <= 2000/12/31的記錄進入第二個分區;
DateTime > 2000/12/31 且 <= 2001/12/31的記錄進入第三個分區;
DateTime > 2001/12/31的記錄進入第四個分區。
RANGE LEFT指定應該進入左邊分區的邊界值,例如小於或等於1999/12/31的值都應該進入第一個分區,下一個值就應該進入第二個分區了。若是使用RANGE RIGHT,邊界值以及大於邊界值的值都應該進入右邊的分區,所以在這個例子中,邊界值2000/12/31就應該進入第二個分區,小於這個邊界值的值就應該進入第一個分區。
3)建立分區方案
經過分區方案在表/索引的分區和存儲它們的文件組之間創建映射關係。建立分區方案的命令以下:
CREATE PARTITION SCHEME OrderDatePScheme AS PARTITION FNOrderDateRange
TO ([1999], [2000], [2001], [2002])
在上面的命令中,咱們指定了:
第一個分區應該進入1999文件組;
第二個分區就進入2000文件組;
第三個分區進入2001文件組;
第四個分區進入2002文件組。
4)在表上應用分區
至此,咱們定義了必要的分區原則,如今須要作的就是給表分區了。首先使用DROP INDEX命令刪除表上現有的彙集索引,一般主鍵上有彙集索引,若是是刪除主鍵上的索引,還能夠經過DROP CONSTRAINT刪除主鍵來間接刪除主鍵上的索引,以下面的命令刪除PK_Orders主鍵:
ALTER TABLE Orders DROP CONSTRAINT PK_Orders;
在分區方案上從新建立彙集索引,命令以下:
CREATE UNIQUE CLUSTERED INDEX PK_Orders ON Orders(OrderDate) ON
OrderDatePScheme (OrderDate)
假設OrderDate列的數據在表中是惟一的,表將基於分區方案OrderDatePScheme被分區,最終被分紅四個小的部分,存放在四個文件組中。若是你對如何分區還有不清楚的地方,建議你去看看微軟的官方文章「SQL Server 2005中的分區表和索引」(地址:http://msdn.microsoft.com/en-us/library/ms345146%28SQL.90%29.aspx)。
第十一步:使用TSQL模板更好地管理DBMS對象(額外的一步)
爲了更好地管理DBMS對象(存儲過程,函數,視圖,觸發器等),須要遵循一致的結構,但因爲某些緣由(主要是時間限制),咱們未能維護一個一致的結構,所以後來遇到性能問題或其它緣由須要從新調試這些代碼時,那感受就像是作噩夢。
爲了幫助你們更好地管理DBMS對象,我建立了一些TSQL模板,利用這些模板你能夠快速地開發出結構一致的DBMS對象。
若是你的團隊有人專門負責檢查團隊成員編寫的TSQL代碼,在這些模板中專門有一個「審查」段落用來描寫審查意見。
我提交幾個常見的DBMS對象模板,它們是:
Template_StoredProcedure.txt:存儲過程模板(http://www.codeproject.com/KB/database/OrganizeFilesAndPartition/Template_StoredProcedure.txt)
Template_View.txt:視圖模板(http://www.codeproject.com/KB/database/OrganizeFilesAndPartition/Template_Trigger.txt)
Template_Trigger.txt:觸發器模板(http://www.codeproject.com/KB/database/OrganizeFilesAndPartition/Template_ScalarFunction.txt)
Template_ScalarFunction.txt:標量函數模板(http://www.codeproject.com/KB/database/OrganizeFilesAndPartition/Template_TableValuedFunction.txt)
emplate_TableValuedFunction.txt:表值函數模板(http://www.codeproject.com/KB/database/OrganizeFilesAndPartition/Template_View.txt)
1)如何建立模板?
首先下載前面給出的模板代碼,然打開SQL Server管理控制檯,點擊「查看」*「模板瀏覽器」;
點擊「存儲過程」節點,點擊右鍵,在彈出的菜單中選擇「新建」*「模板」,爲模板取一個易懂的名字;
在新建立的模板上點擊右鍵,選擇「編輯」,在彈出的窗口中輸入身份驗證信息,點擊「鏈接」;
鏈接成功後,在編輯器中打開下載的Template_StoredProcedure.txt,拷貝文件中的內容粘貼到新建的模板中,而後點擊「保存」。
上面是建立一個存儲過程模板的過程,建立其它DBMS對象過程相似。
2)如何使用模板?
建立好模板後,下面就演示如何使用模板了。
首先在模板瀏覽器中,雙擊剛剛建立的存儲過程模板,彈出身份驗證對話框,輸入對應的身份信息,點擊「鏈接」;
鏈接成功後,模板將會在編輯器中打開,變量將會賦上適當的值;
按Ctrl+Shift+M爲模板指定值,以下圖所示;
圖 1 爲模板參數指定值
點擊「OK」,而後在SQL Server管理控制檯中選擇目標數據庫,而後點擊「執行」按鈕;
若是一切順利,存儲過程就建立成功了。你能夠根據上面的步驟建立其它DBMS對象。
小結
優化講究的是一種「心態」,在優化數據庫性能時,首先要相信性能問題老是能夠解決的,而後就是結合經驗和最佳實踐努力進行優化,最重要的是要儘可能預防性能問題的發生,在開發和部署期間,要利用一切可利用的技術和經驗進行提早評估,千萬不要等問題出現了纔去想辦法解決,在開發期間多花一個小時實施最佳實踐,最後可能會給你節約上百小時的故障診斷和排除時間,要學會聰明地工做,而不是辛苦地工做!