1. 程式人生 > >(轉)SQLServer_十步優化SQL Server中的資料訪問五

(轉)SQLServer_十步優化SQL Server中的資料訪問五

 

  第九步:合理組織資料庫檔案組和檔案

  建立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物件。

  小結

  優化講究的是一種“心態”,在優化資料庫效能時,首先要相信效能問題總是可以解決的,然後就是結合經驗和最佳實踐努力進行優化,最重要的是要儘量預防效能問題的發生,在開發和部署期間,要利用一切可利用的技術和經驗進行提前評估,千萬不要等問題出現了才去想辦法解決,在開發期間多花一個小時實施最佳實踐,最後可能會給你節約上百小時的故障診斷和排除時間,要學會聰明地工作,而不是辛苦地工作!