SQL Server 2005 中的分區表和索引

文章來源:http://msdn.microsoft.com/zh-cn/library/ms345146(SQL.90).aspx

SQL Server 2005 中的分區表和索引

SQL Server 2005
67(共 81)對本文的評價是有幫助 - 評價此主題
發佈日期 : 3/24/2005 | 更新日期 : 3/24/2005

Kimberly L. Tripp
SQLskills.com 的創始人

適用於:
SQL Server 2005

摘要:SQL Server 2005 中基於表的分區功能爲簡化分區表的創建和維護過程提供了靈活性和更好的性能。追溯從邏輯分區表和手動分區表的功能到最新分區功能的發展歷程,探索爲什麼、何時以及如何使用 SQL Server 2005 設計、實現和維護分區表。(本文包含一些指向英文站點的鏈接。)

關於本文本文所描繪的功能和計劃是下一版本 SQL Server 的開發方向。它們並非本產品的說明書,如有更改,恕不另行通知。對於最終產品是否具有這些功能不做任何明示或暗示的保證。對於某些功能,本文假設讀者熟悉 SQL Server 2000 功能和服務。有關背景信息,請訪問 SQL Server 網站SQL Server 2000 資源工具包。這並不是產品說明書。

下載相關的代碼示例 SQL2005PartitioningScripts.exe

本頁內容

爲什麼要進行分區?
分區的發展歷史
定義和術語
創建分區表的步驟
融會貫通:案例研究
總結

爲什麼要進行分區?

什麼是分區?爲什麼要使用分區?簡單的回答是:爲了改善大型表以及具有各種訪問模式的表的可伸縮性和可管理性。通常,創建表是爲了存儲某種實體(例如客戶或銷售)的信息,並且每個表只具有描述該實體的屬性。一個表對應一個實體是最容易設計和理解的,因此不需要優化這種表的性能、可伸縮性和可管理性,尤其是在表變大的情況下。

大型表是由什麼構成的呢?超大型數據庫 (VLDB) 的大小以數百 GB 計算,甚至以 TB 計算,但這個術語不一定能夠反映數據庫中各個表的大小。大型數據庫是指無法按照預期方式運行的數據庫,或者運行成本或維護成本超出預定維護要求或預算要求的數據庫。這些要求也適用於表;如果其他用戶的活動或維護操作限制了數據的可用性,則可以認爲表非常大。例如,如果性能嚴重下降,或者每天、每週甚至每個月的維護期間有兩個小時無法訪問數據,則可以認爲銷售表非常大。有些情況下,週期性的停機時間是可以接受的,但是通過更好的設計和分區實現,通常可以避免或最大程度地減少這種情況的發生。雖然術語 VLDB 僅適用於數據庫,但對分區來說,瞭解表的大小更重要。

除了大小之外,當表中的不同行集擁有不同的使用模式時,具有不同訪問模式的表也可能會影響性能和可用性。儘管使用模式並不總是在變化(這也不是進行分區的必要條件),但在使用模式發生變化時,通過分區可以進一步改善管理、性能和可用性。還以銷售表爲例,當前月份的數據可能是可讀寫的,但以往月份的數據(通常佔表數據的大部分)是隻讀的。在數據使用發生變化的類似情況下,或在維護成本隨着在表中讀寫數據的次數增加而變得異常龐大的情況下,表響應用戶請求的能力可能會受到影響。相應地,這也限制了服務器的可用性和可伸縮性。

此外,如果以不同的方式使用大量數據集,則需要經常對靜態數據執行維護操作。這可能會造成代價高昂的影響,例如性能問題、阻塞問題、備份(空間、時間和運營成本),還可能會對服務器的整體可伸縮性產生負面影響。

分區可以帶來什麼幫助?當表和索引變得非常大時,分區可以將數據分爲更小、更容易管理的部分,從而提供一定的幫助。本文重點介紹橫向分區,在橫向分區中,大量的行組存儲在多個相互獨立的分區中。分區集的定義根據需要進行自定義、定義和管理。Microsoft SQL Server 2005 允許您根據特定的數據使用模式,使用定義的範圍或列表對錶進行分區。SQL Server 2005 還圍繞新的表和索引結構設計了幾種新功能,爲分區表和索引的長期管理提供了大量的選項。

此外,如果具有多個 CPU 的系統中存在一個大型表,則對該表進行分區可以通過並行操作獲得更好的性能。通過對各個並行子集執行多項操作,可以改善在極大型數據集(例如數百萬行)中執行大規模操作的性能。通過分區改善性能的例子可以從以前版本中的聚集看出。例如,除了聚集成一個大型表外,SQL Server 還可以分別處理各個分區,然後將各個分區的聚集結果再聚集起來。在 SQL Server 2005 中,連接大型數據集的查詢可以通過分區直接受益;SQL Server 2000 支持對子集進行並行連接操作,但需要動態創建子集。在 SQL Server 2005 中,已分區爲相同分區鍵和相同分區函數的相關表(如 OrderOrderDetails 表)被稱爲已對齊。當優化程序檢測到兩個已分區且已對齊的表連接在一起時,SQL Server 2005 可以先將同一分區中的數據連接起來,然後再將結果合併起來。這使 SQL Server 2005 可以更有效地使用具有多個 CPU 的計算機。

分區的發展歷史

分區的概念對 SQL Server 來說並不陌生。實際上,此產品的每個版本中都可以實現不同形式的分區。但是,由於沒有爲了幫助用戶創建和維護分區架構而專門設計一些功能,因此分區一直是一個很繁瑣的過程,沒有得到充分的利用。而且,用戶和開發人員對此架構存在誤解(由於其數據庫設計比較複雜),低估了它的優點。但是,由於概念中固有的重要性能改善,SQL Server 7.0 開始通過分區視圖實現各種分區方式,以此來改進這種功能。現在,SQL Server 2005 爲通過分區表對大型數據集進行分區又邁出了最大的一步。

對 SQL Server 7.0 之前的版本中的對象進行分區

在 SQL Server 6.5 及以前的版本中,分區只能通過設計來完成,還必須內置到所有數據訪問編碼和查詢方法中。通過創建多個表,然後通過存儲過程、視圖或客戶端應用程序管理對正確表的訪問,通常可以改善某些操作的性能,但代價是增加了設計的複雜性。每個用戶和開發人員都必須知道(並正確引用)正確的表。單獨創建和管理每個分區,而使用視圖來簡化訪問;但是這種解決方案對性能並沒有太大的改善。使用聯合視圖簡化用戶和應用程序訪問時,查詢處理器必須訪問每個基礎表才能確定結果集所需的數據。如果只需要基礎表的有限子集,則每個用戶和開發人員都必須瞭解此設計,以便只引用相應的表。

SQL Server 7.0 中的分區視圖

在 SQL Server 7.0 之前的版本中,手動創建分區所面臨的挑戰主要與性能有關。儘管視圖可以簡化應用程序設計、用戶訪問和查詢的編寫,但卻無法改善性能。而在 SQL Server 7.0 版本中,視圖結合了約束,允許查詢優化程序從查詢計劃中刪除不相關的表(即分區消除),大大降低了聯合視圖訪問多個表時的總計劃成本。

請參見圖 1 中的 YearlySales 視圖。您可以定義十二個單獨的表(如 SalesJanuary2003SalesFebruary2003 等),然後定義每個季度的視圖以及全年的視圖 YearlySales,而不是將所有銷售數據放到一個大型表中。

ms345146.sql2k5partition_01(zh-cn,SQL.90).gif

圖 1 : SQL Server 7.0/2000 中的分區視圖

使用以下查詢訪問 YearlySales 視圖的用戶只會被引導至 SalesJanuary2003 表。

SELECT ys.* 
FROM dbo.YearlySales AS ys
WHERE ys.SalesDate = '20030113' 

只要約束可信並且訪問視圖的查詢使用 WHERE 子句根據分區鍵(定義約束的列)限制查詢結果,SQL Server 就會只訪問必需的基礎表。受信任的約束是指 SQL Server 能夠確保所有數據符合該約束所定義的屬性的約束。創建約束時,默認行爲是創建約束 WITH CHECK。此設置將導致對錶執行架構鎖定,以便根據約束驗證數據。如果驗證結果表明現有數據有效,則添加約束;一旦解除架構鎖定,後續的插入、更新和刪除操作都必須符合正在應用的約束。通過使用此過程創建受信任的約束,開發人員無需直接訪問(甚至不需要知道)他們感興趣的表,從而大大降低了使用視圖的設計的複雜性。通過受信任的約束,SQL Server 可以從執行計劃中刪除不需要的表,從而改善性能。

注意:約束可以通過各種方式變得“不可信任”;例如,如果未指定 CHECK_CONSTRAINTS 參數即執行批量插入,或者使用 NOCHECK 創建約束。如果約束不可信任,查詢處理器將轉而掃描所有基礎表,因爲它無法確定所請求的數據是否真的位於正確的基礎表中。

SQL Server 2000 中的分區視圖

儘管 SQL Server 7.0 大大簡化了設計並改善了 SELECT 語句的性能,但是並沒有爲數據修改語句帶來任何好處。INSERT、UPDATE 和 DELETE 語句只能針對基礎表,而不能直接針對用於聯合表的視圖。在 SQL Server 2000 中,數據修改語句還可以受益於 SQL Server 7.0 中引入的分區視圖功能。由於數據修改語句可以使用相同的分區視圖結構,因此,SQL Server 可以通過視圖將修改定向至相應的基礎表。爲了正確配置此設置,需要對分區鍵及其創建設置額外的限制;但是,基本原理是相同的,因爲 SELECT 查詢與修改都會直接發送給相應的基礎表。有關在 SQL Server 2000 中進行分區的限制、設置、配置和最佳方法的詳細信息,請參見 Using Partitions in a Microsoft SQL Server 2000 Data Warehouse

SQL Server 2005 中的分區表

儘管 SQL Server 7.0 和 SQL Server 2000 中的改進大大改善了使用分區視圖時的性能,但是並沒有簡化分區數據集的管理、設計或開發。使用分區視圖時,必須單獨創建和管理每個基礎表(在其中定義視圖的表)。儘管簡化了應用程序設計併爲用戶帶來了好處(用戶不再需要知道直接訪問哪個基礎表),但是由於要管理的表太多,而且必須爲每個表管理數據完整性約束,管理工作變得更復雜。因爲管理方面的問題,通常只有在需要存檔或加載數據時才使用分區視圖來分離表。當數據被移動到只讀表或從只讀表中刪除後,操作的代價變得十分高昂,不僅花費時間、佔據日誌空間,通常還會導致系統阻塞。

另外,由於以前版本中的分區策略需要開發人員創建各個表和索引,然後通過視圖將它們聯合起來,因此優化程序需要驗證並確定每個分區的計劃(因爲索引可能已發生變化)。這樣一來,SQL Server 2000 中的查詢優化時間通常會隨着處理的分區數增加而直線上升。

在 SQL Server 2005 中,從定義上講,每個分區都擁有相同的索引。例如,請考慮這樣一種方案,即當前月份的聯機事務處理 (OLTP) 數據需要移動到每個月末的分析表中。分析表(用於只讀查詢)是具有一個羣集索引和兩個非羣集索引的表;批量加載 1 GB 數據(加載到已建立索引並激活的一個表中)將使當前用戶遭受系統阻塞的情況,因爲表和/或索引變得支離破碎和/或被鎖定。另外,因爲每傳入一行都需要維護表和索引,所以加載過程還將耗費大量的時間。雖然可以通過多種方法加快批量加載的速度,但這些方法可能會直接影響所有其他用戶,因爲追求速度而無法實現併發操作。

如果將這些數據單獨放到一個新創建的(空)且未建立索引(堆)的表中,則可以先加載數據,而在加載數據之後建立索引。通常情況下,使用這種架構可以獲得十倍或更好的性能。實際上,通過加載未建立索引的表可以利用多個 CPU,因爲可以並行加載多個數據文件或從同一個文件中加載多個數據塊(通過開始和結束行位置來定義)。由於兩個操作都可以通過並行獲益,因此可以更進一步改善性能。

在 SQL Server 的任何版本中,分區都使您可以獲得更精確的控制,而且不需要將所有數據放到一個位置;但是,需要創建和管理許多對象。在以前的版本中,通過動態創建表、刪除表以及修改聯合視圖,可以實現功能性分區策略。但是,SQL Server 2005 中的解決方案更加完善:您可以輕鬆地移入新填充的分區(作爲現有分區架構的額外分區),還可以移出任何舊分區。整個過程只需要很短的時間即可完成,通過使用並行批量加載和並行索引建立,還可以進一步提高效率。更重要的是,因爲分區是在表範圍之外進行管理的,所以添加分區之前不會對所查詢的表造成任何影響。結果是,添加一個分區通常只需要幾秒鐘。

需要刪除數據時的性能改善也很顯著。如果一個數據庫需要一個滑動窗口數據集,用於移植新數據(例如當前月份的數據)並刪除最早的數據(可能是上一年同一月份的數據),那麼使用分區可以將數據移植的性能提高几個數量級。雖然這看起來好像很大,但考慮了未分區的區別;當所有數據位於一個表中時,刪除 1 GB 的舊數據需要對錶及其相關索引進行逐行處理。刪除數據的過程將創建大量的日誌活動,不允許在刪除的過程中出現日誌截斷問題(注意,刪除是一個自動提交的事務;但是,可以通過儘可能地執行多個刪除操作來控制事務的大小),因此,可能需要更大的日誌。但是,如果使用分區,刪除相同數量的數據需要從分區表中刪除特定的分區(一種元數據操作),然後刪除或截斷獨立的表。

此外,如果不知道如何才能最好地設計分區,則不可能認識到將文件組與分區結合使用是實現分區的理想選擇。文件組允許您將各個表放置到不同的物理磁盤上。如果一個表包含多個文件(使用文件組),則無法預測數據的物理位置。對於不需要使用並行操作的系統來說,SQL Server 可以在文件組之間更平均地使用所有磁盤,使數據具體放在什麼位置變得不是那麼重要,從而提高系統的性能。

注意:在圖 2 中,一個文件組包含三個文件。此文件組中放置了兩個表,即 OrdersOrderDetails。將表放置到文件組中時,SQL Server 將根據文件組中的對象需要的空間,從每個文件中獲得盤區分配(64-KB 塊,相當於八個 8-KB 頁面),按比例填充文件組中的文件。創建 OrdersOrderDetails 表時,文件組是空的。創建訂單時,數據被輸入到 Orders 表中(每個訂單佔據一行),並且按照每個明細項一行的方式輸入到 OrderDetails 表中。SQL Server 將一個盤區分配給文件 1 中的 Orders 表,將另一個盤區分配給文件 2 中的 OrderDetails 表。OrderDetails 表的增長速度可能比 Orders 錶快,後續的分配將轉到下一個需要空間的表中。隨着 OrderDetails 表的增長,它將從文件 3 中獲取下一個盤區,而 SQL Server 將繼續在文件組的文件之間“循環”下去。在圖 2 中,就是從每個表到盤區,再從每個盤區到相應的文件組。盤區是按照需要的空間進行分配的,而根據流程進行編號。

ms345146.sql2k5partition_02(zh-cn,SQL.90).gif

圖 2 :使用文件組進行分區填充

SQL Server 繼續在文件組中的所有對象之間平衡分配。如果增加給定操作使用的磁盤數,雖然 SQL Server 可以更有效地運行,但從管理或維護的角度來說,增加磁盤數並非最佳選擇,尤其是在使用模式幾乎可以預測(且已隔離)的情況下。因爲數據在磁盤上的位置並不明確,所以您無法隔離數據以執行備份等維護操作。

通過 SQL Server 2005 中的分區表,可以對錶進行設計(使用函數和架構),從而將具有相同分區鍵的所有行都直接放置到(且總是轉到)特定的位置。函數用於定義分區邊界以及放置第一個值的分區。在使用 LEFT 分區函數時,第一個值將作爲第一個分區中的上邊界。在使用 RIGHT 分區函數時,第一個值將作爲第二個分區的下邊界(本文後面將更詳細地介紹分區函數)。定義函數後即可創建分區架構,以定義分區到其數據庫位置的物理映射(根據分區函數)。當多個表使用同一個函數(但不一定使用同一個架構)時,將按類似的方式對具有相同分區鍵的行進行分組。此概念稱爲對齊。通過將來自多個表但具有相同分區鍵的行對齊到相同或不同的物理磁盤上,SQL Server 可以(如果優化程序做出此選擇)只處理每個表中必要的數據組。要實現對齊,兩個分區表或索引所在的相應分區之間必須具有某種對應性。它們必須爲分區列使用等效的分區函數。如果滿足以下條件,兩個分區函數則可以用來對齊數據:

  • 兩個分區函數使用相同數量的參數和分區。

  • 每個函數中使用的分區鍵具有相同的類型(包括長度和精度,如果適用,還包括縮放和排序)。

  • 邊界值相等(包括 LEFT/RIGHT 邊界標準)。

注意:即使兩個分區函數都用於對齊數據,但如果沒有在與分區表相同的列上分區,最後的索引也可能無法對齊。

排序是一種更強大的對齊方式,通過排序,兩個對齊的對象將用一個 equi-join 謂詞連接起來(equi-join 位於分區列上)。在可能出現 equi-join 謂詞的查詢、子查詢或其他類似結構的上下文中,這變得很重要。排序之所以重要,因爲在分區列上連接表的查詢一般都非常快。以圖 2 中的 OrdersOrderDetails 表爲例,除了按比例填充文件之外,還可以創建映射到三個文件組的分區架構。定義 OrdersOrderDetails 表時,將它們定義爲使用相同的架構。具有相同分區鍵值的相關數據將被放置到同一個文件中,而將必要的數據隔離出來以便進行連接。如果來自多個表的相關行都按照相同的方式進行分區,SQL Server 則可以連接分區,而無需在整個表或多個分區中(如果表使用了不同的分區函數)搜索匹配的行。在這種情況下,不僅可以對齊對象(因爲它們使用相同的鍵),還可以按存儲位置對齊(因爲相同的數據位於相同的文件中)。

圖 3 顯示兩個對象可以使用相同的分區架構,而具有相同分區鍵的所有數據行最後將位於同一個文件組中。對齊相關數據後,SQL Server 2005 可以有效地並行處理大型數據集。例如,1 月份的所有銷售數據(包括 OrdersOrderDetails 表中的數據)都位於第一個文件組中,2 月份的數據位於第二個文件組中,依此類推。

ms345146.sql2k5partition_03(zh-cn,SQL.90).gif

圖 3 :按存儲位置對齊的表

SQL Server 允許根據範圍進行分區,還允許將表和索引都設計爲使用相同的架構,以便更好地對齊。好的設計可以大大提高整體性能,但是,如果數據的使用隨着時間而發生變化,該怎麼辦?如果需要額外的分區,又該怎麼辦?簡化從分區表外部添加分區、刪除分區和管理分區等方面的管理工作是 SQL Server 2005 的主要設計目標。

SQL Server 2005 已經考慮瞭如何簡化分區的管理、開發和使用。它在性能和可管理性方面有以下優點:

  • 簡化了需要進行分區以改善性能或可管理性的大型表的設計和實現。

  • 將數據加載到現有分區表的新分區中時,最大程度地減少了對其他分區中的數據訪問的影響。

  • 將數據加載到現有分區表的新分區中時,性能相當於將同樣的數據加載到新的空表中。

  • 在存檔和/或刪除分區表的一個分區時,最大程度地減少了對錶中其他分區的訪問的影響。

  • 允許通過將分區移入和移出分區表來維護分區。

  • 提供了更好的伸縮性和並行性,可以對多個相關表執行大量操作。

  • 改善了所有分區的性能。

  • 縮短了查詢優化時間,因爲不需要單獨優化每個分區。

定義和術語

要在 SQL Server 2005 中實現分區,必須瞭解一些新的概念、術語和語法。要理解這些新概念,首先我們看一下與創建和放置操作有關的表結構。在以前的版本中,表通常是一個物理和邏輯概念,但使用 SQL Server 2005 分區表和索引,您在存儲表的方式和位置方面就有了多種選擇。在 SQL Server 2005 中,可以使用以前版本中的相同語法創建表和索引,作爲一個表結構放置到 DEFAULT 文件組或用戶定義的文件組中。另外,在 SQL Server 2005 中,還可以根據分區架構創建表和索引。分區架構可以將對象映射到一個或多個文件組。爲了確定數據的相應物理位置,分區架構將使用了分區函數。分區函數定義了用來定向行的算法,而架構則將分區與其相應的物理位置(即文件組)相關聯。換句話說,表仍然是一個邏輯概念,但與以前的版本相比,表在磁盤上的物理位置有了很大的不同;表還可以擁有架構。

範圍分區

範圍分區是按照特定和可定製的數據範圍定義的表分區。範圍分區的邊界由開發人員選擇,還可以隨着數據使用模式的變化而變化。通常,這些範圍是根據日期或排序後的數據組進行劃分的。

範圍分區主要用於數據存檔、決策支持(當通常只需要特定範圍內的數據時,例如給定的月份或季度)以及組合的 OLTP 和決策支持系統 (DSS)(數據使用在行的生命週期內會發生變化)。SQL Server 2005 分區表和索引的最大優點,尤其是在存檔和維護方面,就是可以管理特定範圍內的數據。通過範圍分區,可以非常快速地存檔和替換舊的數據。當數據訪問通常用於對大範圍數據的決策支持時,最適合使用範圍分區。在這種情況下,數據所在的具體位置至關重要,這樣才能在需要時只訪問相應的分區。另外,由於事務數據已經可用,因此可以輕鬆快捷地添加數據。範圍分區最初定義起來很複雜,因爲需要爲每個分區定義邊界條件。此外,還需要創建一個架構,將每個分區映射到一個或多個文件組。但是,它們通常具有一致的模式,因此,定義後很容易通過編程方式進行維護(參見圖 4)。

ms345146.sql2k5partition_04(zh-cn,SQL.90).gif

圖 4 :具有 12 個分區的範圍分區表

定義分區鍵

對錶和索引進行分區的第一步就是定義分區的關鍵數據。分區鍵必須作爲一個列存在於表中,還必須滿足一定的條件。分區函數定義鍵(也稱爲數據的邏輯分離)所基於的數據類型。函數只定義鍵,而不定義數據在磁盤上的物理位置。數據的位置由分區架構決定。換句話說,架構將數據映射到一個或多個文件組,文件組將數據映射到特定的文件,文件又將數據映射到磁盤。分區架構通常使用函數來實現此目的:如果函數定義了五個分區,則架構必須使用五個文件組。文件組不需要各不相同;但是,如果擁有多個磁盤(最好是多個 CPU),使用不同的文件組可以獲得更好的性能。將架構與表一起使用時,您需要定義用作分區函數的參數的列。

對於範圍分區,數據集可以根據邏輯和數據驅動的邊界進行劃分。實際上,數據分區不可能實現真正的平衡。當以定義分析的特定邊界(也稱爲範圍)的方式使用表時,數據的使用即表明範圍分區。範圍函數的分區鍵可以只包含一個列,而分區函數可以包含整個域,即使表中可能不存在數據(由於數據完整性/約束)。換句話說,可以爲每個分區定義邊界,但第一個分區和最後一個分區可能包含最左側的行(小於最低邊界條件的值)和最右側的行(大於最高邊界條件的值)。因此,要將值域限制到特定的數據集,必須將分區與 CHECK 約束結合使用。使用 CHECK 約束強制應用業務規則和數據完整性約束,使您可以將數據集限制到特定的範圍,而不是不確定的範圍。當維護和管理過程中需要定期存檔大量數據,當查詢訪問範圍子集內的大量數據時,範圍分區是理想的選擇。

索引分區

除了對錶的數據集進行分區之外,還可以對索引進行分區。使用相同的函數對錶及其索引進行分區通常可以優化性能。當索引和表按照相同的順序使用相同的分區函數和列時,表和索引將對齊。如果在已經分區的表中建立索引,SQL Server 會自動將新索引與該表的分區架構對齊,除非該索引的分區明顯不同。當表及其索引對齊後,SQL Server 則可以更有效地將分區移入和移出分區表,因爲所有相關的數據和索引都使用相同的算法進行劃分。

如果定義表和索引時不僅使用了相同的分區函數,還使用了相同的分區架構,則這些表和索引將被認爲是按存儲位置對齊。按存儲位置對齊的一個優點是,相同邊界內的所有數據都位於相同的物理磁盤上。在這種情況下,可以單獨在某個時間段內執行備份操作,還可以根據數據的變化在備份頻率和備份類型方面改變您的策略。如果連接或收集了相同文件或文件組中的表和索引,則可以發現更多的好處。SQL Server 可以通過在多個分區中並行操作來獲益。在按存儲位置對齊和多 CPU 的情況下,每個處理器都可以直接處理特定的文件或文件組,而不會與數據訪問產生任何衝突,因爲所有需要的數據都位於同一個磁盤上。這樣,可以並行運行多個進程,而不會相互干擾。

有關詳細信息,請參見 SQL Server Books Online 中的“Special Guidelines for Partitioned Indexes”。

分區的特殊情況:拆分、合併和移動

爲了更好地使用分區表,需要了解與分區管理有關的幾個新功能和概念。因爲分區適用於可以縮放的大型表,所以創建分區函數時選擇的分區數隨着時間而變化。可以將 ALTER TABLE 語句與新的拆分選項結合使用,在表中添加一個分區。拆分分區時,可以將數據移動到新的分區中;但是爲了維護性能,不應移動行。本文後面的案例研究將介紹這種方案。

相反,要刪除分區,請先移出數據,然後合併邊界點。如果使用範圍分區,則通過指明應刪除的邊界點來發出合併請求。在只需要特定時段的數據並且定期進行數據存檔(例如,每月一次)的情況下,您可能希望在當前月份的數據可用時存檔部分數據(最早月份的數據)。例如,您可以選擇獲取一年的數據,而在每個月末移入當前月份,然後移出最早的月份,從而區分當前月份的讀/寫 OLTP 與以前月份的只讀數據。如以下方案所述,可以通過一個特殊的操作流使處理更有效。

您保留了一年的只讀數據。目前,表中的數據是從 2003 年 9 月到 2004 年 8 月的數據。而當前月份 2004 年 9 月位於另一個數據庫中,併爲 OLTP 性能而進行了優化。在只讀版本的表中,共有 13 個分區:十二個分區包含數據(從 2003 年 9 月到 2004 年 8 月),最後一個分區是空的。最後這個分區爲空的原因在於,範圍分區總是包括整個域,即最左側和最右側。如果您打算在滑動窗口方案中管理數據,通常需要有一個可以拆分的空分區,以便放置新數據。在使用 LEFT 邊界點定義的分區函數中,空分區邏輯上位於最右側。將最後一個分區保留爲空使您可以拆分空分區(用來存儲即將產生的新數據),而且不需要將最後一個分區的行(因爲不存在)移動到添加(拆分空分區以存儲其他數據塊時進行此操作)的新文件組中。這是一個相當複雜的概念,將在本文後面的案例研究中進行更詳細的介紹,但其核心思想是,所有數據添加或刪除操作都應該只是元數據操作。爲了確保只進行元數據操作,需要從策略上管理表中不斷變化的那個分區。爲了確保此分區爲空的,您需要使用 CHECK 約束將此數據限定在基礎表中。在這種情況下,OrderDate 應該在 2003 年 9 月 1 日之後(包括此日),在 2004 年 9 月 1 日之前。如果最後定義的邊界點是 8 月 31 日 11:59:59.997(爲什麼是 997,後文有詳細的說明),則分區函數與此約束的組合將使最後一個分區爲空。雖然這些只是概念,但重要的是要了解拆分和合並是通過 ALTER PARTITION FUNCTION 進行的,而移動是通過 ALTER TABLE 進行的。

ms345146.sql2k5partition_05(zh-cn,SQL.90).gif

圖 5 :加載 / 存檔數據前的範圍分區邊界

進入 10 月份後(在 OLTP 數據庫中),9 月份的數據應移到分區表中,用於進行分析。移入和移出表的過程非常快,而且準備工作可以在分區表外完成。後面的案例研究中會對此方案進行深入的解釋,但核心思想是,您可以使用“分段表”,該表最終將成爲分區表中的一個分區。本文後面的案例研究中會詳細介紹此方案。在此過程中,您將表的一個分區移出(參見圖 6)到相同文件組內的一個非分區表中。因爲相同文件組中已經存在非分區表(這是成功的關鍵),SQL Server 可以將此移動視爲元數據更改。因爲只是元數據更改,所以可以在幾秒鐘內完成,而不需要執行可能需要幾小時並在大型表中產生阻塞的刪除操作。移出此分區後,您仍然擁有 13 個分區;第一個(最舊的)分區現在是空的,最後一個(最近的,也是空的)分區是需要拆分的。

ms345146.sql2k5partition_06(zh-cn,SQL.90).gif

圖 6 :移出分區

要刪除最舊的分區(2003 年 9 月),請將新的合併選項(如圖 7 所示)與 ALTER TABLE 結合使用。有效地合併邊界點將刪除邊界點,從而刪除分區。這將加載數據的分區數減少到 n-1(本例中爲 12)。如果不需要移動行,合併分區應該是一個非常快的操作(因爲要合併的邊界點沒有數據行)。在本例中,因爲第一個分區爲空,不需要從第一個分區向第二個分區中移動任何行。如果在第一個分區非空的情況下合併邊界點,必須將第一個分區的行移動到第二個分區中,這可能是一個代價非常高昂的操作。但是,在最常見的滑動窗口方案中(空分區與活動分區合併,並且不移動任何行),不需要執行此操作。

ms345146.sql2k5partition_07(zh-cn,SQL.90).gif

圖 7 :合併分區

最後,必須將新表移入分區表。要將此操作作爲元數據更改來執行,必須在新表中(分區表的邊界之外)加載和建立索引。要移入分區,請先將最後一個範圍和最近一個空範圍拆分爲兩個分區。另外,還需要更新表的約束以允許新的範圍。分區表將再次擁有 13 個分區。在滑動窗口方案中,使用 LEFT 分區函數的最後一個分區將始終爲空。

ms345146.sql2k5partition_08(zh-cn,SQL.90).gif

圖 8 :拆分分區

最後,新加載的數據已準備就緒,可以移入第十二個分區,即 2004 年 9 月。

ms345146.sql2k5partition_09(zh-cn,SQL.90).gif

圖 9 :移入分區

表的結果是:

ms345146.sql2k5partition_10(zh-cn,SQL.90).gif

圖 10 :加載 / 存檔數據後的範圍分區邊界

因爲一次只能添加或刪除一個分區,所以應重新創建需要添加或刪除多個分區的表。要更改爲這種新的分區結構,請先創建新的分區表,然後將數據加載到新創建的表中。與每次拆分後重新平衡整個表相比,這種方法更好。此過程是使用新的分區函數和新的分區架構,然後將數據移動到新分區的表中來完成的。要移動數據,請先使用 INSERT newtable SELECT columnlist FROM oldtable 複製數據,然後刪除原始表。用戶不應在此過程中修改數據,以防數據丟失。

有關詳細信息,請參見 SQL Server Books Online 中的“ALTER PARTITION FUNCTION”和“ALTER TABLE”。

創建分區表的步驟

現在,您對分區表的價值有了一定的瞭解,下一節將詳細介紹實現分區表的過程以及有助於完成此過程的功能。邏輯流程如下:

ms345146.sql2k5partition_11(zh-cn,SQL.90).gif

圖 11 :創建分區表或索引的步驟

確定是否應爲對象分區

雖然分區可以帶來衆多的好處,但也增加了實現對象的管理費用和複雜性,這可能是得不償失的。尤其是,您可能不需要爲較小的表或目前滿足性能和維護要求的表分區。前面提到的銷售方案使用分區減輕了移動行和數據的負擔,但在決定是否實現分區時,您應考慮您的方案是否存在這種負擔。

確定分區鍵和分區數

如果您正在嘗試改善大型數據子集的性能和可管理性,並且已經定義了訪問模式,則可以使用範圍分區減少數據爭用的情況,同時減少只讀數據不需要分區時的維護工作。要確定分區數,應先評估您的數據中是否存在邏輯分組和模式。如果您通常一次只處理這些已定義子集中的少數幾個,則應定義範圍以隔離查詢,使其只處理相應的數據(即,只處理特定的分區)。

有關詳細信息,請參見SQL Server Books Online中的“Designing Partitioned Tables and Indexes”。

確定是否應使用多個文件組

爲了有助於優化性能和維護,應使用文件組分離數據。文件組的數目一定程度上由硬件資源決定:一般情況下,文件組數最好與分區數相同,並且這些文件組通常位於不同的磁盤上。但是,這主要適用於打算對整個數據集進行分析的系統。如果您有多個 CPU,SQL Server 則可以並行處理多個分區,從而大大縮短處理大量複雜報表和分析的總體時間。這種情況下,可以獲得並行處理以及在分區表中移入和移出分區的好處。

創建文件組

如果需要爲多個文件放置一個分區表以獲得更好的 I/O 平衡,則至少需要創建一個文件組。文件組可以由一個或多個文件構成,而每個分區必須映射到一個文件組。一個文件組可以由多個分區使用,但是爲了更好地管理數據(例如,爲了獲得更精確的備份控制),應該對分區表進行設計,以便只有相關數據或邏輯分組的數據位於同一個文件組中。使用 ALTER DATABASE,可以添加邏輯文件組名,然後添加文件。要爲 AdventureWorks 數據庫創建名爲 2003Q3 的文件組,請按以下方式使用 ALTER DATABASE:

ALTER DATABASE AdventureWorks ADD FILEGROUP [2003Q3]

創建文件組後,使用 ALTER DATABASE 將文件添加到該文件組中。

ALTER DATABASE AdventureWorks
ADD FILE 
(NAME = N'2003Q3',
FILENAME = N'C:\AdventureWorks\2003Q3.ndf',
SIZE = 5MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB)
TO FILEGROUP [2003Q3]

通過在 CREATE TABLE 的 ON 子句中指定一個文件組,可以爲文件創建一個表。但是,如果表未分區,則不能爲多個文件組創建一個表。要爲一個文件組創建表,請使用 CREATE TABLE 的 ON 子句。要創建分區表,必須先確定分區的功能機制。進行分區的標準以分區函數的形式從邏輯上與表相分離。此分區函數作爲獨立於表的定義存在,而這種物理分離將起到幫助作用,因爲多個對象都可以使用該分區函數。因此,爲表分區的第一步是創建分區函數。

爲範圍分區創建分區函數

範圍分區必須使用邊界條件進行定義。而且,即使通過 CHECK 約束對錶進行了限制,也不能消除該範圍任一邊界的值。爲了允許定期將數據移入該表,需要創建最後一個空分區。

在範圍分區中,首先定義邊界點:如果存在五個分區,則定義四個邊界點值,並指定每個值是第一個分區的上邊界 (LEFT) 還是第二個分區的下邊界 (RIGHT)。根據 LEFT 或 RIGHT 指定,始終有一個空分區,因爲該分區沒有明確定義的邊界點。

具體來講,如果分區函數的第一個值(或邊界條件)是 '20001001',則邊界分區中的值將是:

對於 LEFT

第一個分區是所有小於或等於 '20001001' 的數據

第二個分區是所有大於 '20001001' 的數據

對於 RIGHT

第一個分區是所有小於 '20001001' 的數據

第二個分區是所有大於或等於 '20001001' 數據

由於範圍分區可能在 datetime 數據中進行定義,因此必須瞭解其含義。使用 datetime 具有某種含義:即總是同時指定日期和時間。未定義時間值的日期表示時間部分爲“0”的 12:00 A.M。如果將 LEFT 與此類數據結合使用,則日期爲 10 月 1 日 12:00 A.M. 的數據將位於第一個分區,而 10 月份的其他數據將位於第二個分區。從邏輯上講,最好將開始值與 RIGHT 結合使用,而將結束值與 LEFT 結合使用。下面的三個子句將創建邏輯上相同的分區結構:

RANGE LEFT FOR VALUES ('20000930 23:59:59.997',
               '20001231 23:59:59.997', 
               '20010331 23:59:59.997',
               '20010630 23:59:59.997')

RANGE RIGHT FOR VALUES ('20001001 00:00:00.000', '20010101 00:00:00.000', '20010401 00:00:00.000', '20010701 00:00:00.000')

RANGE RIGHT FOR VALUES ('20001001', '20010101', '20010401', '20010701')

注意:此處使用 datetime 數據類型確實增加了一定的複雜性,但您需要確保設置正確的邊界情況。請注意使用 RIGHT 的簡單性,因爲默認時間爲 12:00:00.000 A.M。對於 LEFT,複雜性增加是因爲 datetime 數據類型具有精度。必須選擇 23:59:59.997 的原因在於,datetime 數據無法保證毫秒級別的精度。相反,datetime 數據的精度在 3.33 毫秒內。使用 23:59:59.999 這個確切的時間值是不行的,因爲該值將被舍入到最接近的時間值,即第二天的 12:00:00.000 A.M。由於進行了這種舍入,將無法正確定義邊界。對於 datetime 數據,必須對明確提供的毫秒值加倍小心。

注意:分區函數還允許將函數作爲分區函數定義的一部分。您可以使用 DATEADD(ms,-3,'20010101'),而不是使用 '20001231 23:59:59.997' 明確定義時間。

有關詳細信息,請參見SQL Server Books Online的“Transact-SQL Reference”中的“Date and Time”部分。

要在四個活動分區(每個分區代表一個日曆季度)中存儲四分之一的 Orders 數據,並創建第五個分區以備將來使用(還是作爲佔位符,用於在分區表中移入和移出數據),請將 LEFT 分區函數與以下四個邊界條件結合使用:

CREATE PARTITION FUNCTION OrderDateRangePFN(datetime)
AS
RANGE LEFT FOR VALUES ('20000930 23:59:59.997',
            '20001231 23:59:59.997',
            '20010331 23:59:59.997',
            '20010630 23:59:59.997')

記住,定義四個邊界點將創建五個分區。通過查看以下數據集檢查此分區創建的數據集:

邊界點 '20000930 23:59:59.997' 作爲 LEFT(設置模式):

最左側的分區將包含所有小於或等於 '20000930 23:59:59.997' 的值

邊界點 '20001231 23:59:59.997':

第二個分區將包含所有大於 '20000930 23:59:59.997' 但小於或等於 '20001231 23:59:59.997' 的值

邊界點 '20010331 23:59:59.997':

第三個分區將包含所有大於 '20001231 23:59:59.997' 但小於或等於 '20010331 23:59:59.997' 的值

邊界點 '20010630 23:59:59.997':

第四個分區將包含所有大於 '20010331 23:59:59.997' 但小於或等於 '20010630 23:59:59.997' 的值

最後,第五個分區將包含所有大於 '20010630 23:59:59.997' 的值。

創建分區架構

創建分區函數後,必須將其與分區架構相關聯,以便將分區定向至特定的文件組。定義分區架構時,即使多個分區位於同一個文件組中,也必須爲每個分區指定一個文件組。對於前面創建的範圍分區 (OrderDateRangePFN),存在五個分區;最後一個空分區將在 PRIMARY 文件組中創建。因爲此分區永遠不包含數據,所以不需要指定特殊的位置。

CREATE PARTITION SCHEME OrderDatePScheme 
AS
PARTITION OrderDateRangePFN 
TO ([2000Q3], [2000Q4], [2001Q1], [2001Q2], [PRIMARY])

注意:如果所有分區都位於同一個文件組中,則可以使用以下更簡單的語法:

CREATE PARTITION SCHEME OrderDatePScheme 
AS
PARTITION OrderDateRangePFN 
ALL TO ([PRIMARY])

創建分區表

定義分區函數(邏輯結構)和分區架構(物理結構)後,即可創建表來利用它們。表定義應使用的架構,而架構又定義函數。要將這三者結合起來,必須指定應該應用分區函數的列。範圍分區始終只映射到表中的一列,此列應與分區函數中定義的邊界條件的數據類型相匹配。另外,如果表應明確限制數據集(而不是從負無窮大到正無窮大),則還應添加 CHECK 約束。

CREATE TABLE [dbo].[OrdersRange]  
(
[PurchaseOrderID] [int] NOT NULL,
[EmployeeID] [int] NULL,
[VendorID] [int] NULL,
[TaxAmt] [money] NULL,
[Freight] [money] NULL,
[SubTotal] [money] NULL,
[Status] [tinyint] NOT NULL ,
[RevisionNumber] [tinyint] NULL ,
[ModifiedDate] [datetime] NULL ,
[ShipMethodID] [tinyint] NULL,
[ShipDate] [datetime] NOT NULL, 
   [OrderDate] [datetime] NOT NULL
CONSTRAINT OrdersRangeYear
CHECK ([OrderDate] >= '20030701' 
AND [OrderDate] <= '20040630 11:59:59.997'), 
   [TotalDue] [money] NULL
) 
ON OrderDatePScheme (OrderDate)
GO

建立索引:是否分區?

默認情況下,分區表中創建的索引也使用相同的分區架構和分區列。如果屬於這種情況,索引將與表對齊。儘管未作要求,但將表與其索引對齊可以使管理工作更容易進行,對於滑動窗口方案尤其如此。

例如,要創建唯一的索引,分區列必須是一個關鍵列;這將確保對相應的分區進行驗證,以保證索引的唯一性。因此,如果需要在一列上對錶進行分區,而必須在另一個列上創建唯一的索引,這些表和索引將無法對齊。在這種情況下,可以在唯一的列(如果是多列的唯一鍵,則可以是任一關鍵列)中對索引進行分區,或者根本就不進行分區。請注意,在分區表中移入和移出數據時,必須刪除和創建此索引。

注意:如果您打算使用現有數據加載表並立即在其中添加索引,則通常可以通過以下方式獲得更好的性能:先加載到未分區、未建立索引的表中,然後在加載數據後創建分區索引。通過爲分區架構定義羣集索引,可以在加載數據後更有效地爲表分區。這也是爲現有表分區的不錯方法。要創建與未分區表相同的表並創建與已分區羣集索引相同的羣集索引,請用一個文件組目標位置替換創建表中的 ON 子句。然後,在加載數據之後爲分區架構創建羣集索引。

融會貫通:案例研究

如果您閱讀了與分區有關的概念、優點和代碼示例,則可能已對此過程有了一個很好的理解;但是,對於每個步驟,都可以使用特定的設置和選項,而且在某些情況下,還必須滿足各種條件。本節將幫助您將這些內容融會貫通起來進行理解。

範圍分區:銷售數據

銷售數據的使用方式經常發生變化。當前月份的數據是事務數據,而上一個月份的數據主要用於進行分析。分析通常針對月份、季度和/或年度範圍的數據進行。因爲不同的分析人員可能希望同時查看大量不斷變化的數據,所以通過分區可以更好地隔離此活動。在此方案中,活動數據來自 283 個分支位置,而且是通過兩個標準格式的 ASCII 文件傳輸的。在每個月第一天的上午 3 點之前,所有文件均被放置到一臺中央文件服務器上。所有文件按大小進行排列,但每月平均約有 86,000 份銷售(訂單)。每個訂單平均包含 2.63 個明細項,因此,OrderDetails 文件平均包含 226,180 行。每月增加約 2,500 萬個新的 Orders 和 6,400 萬個 OrderDetails 行,而歷史分析服務器要使兩年的數據都處於活動狀態以便進行分析。兩年的數據剛好低於 6 億個 Orders 和超過 15 億個 OrderDetails 行。因爲分析通常是在同一季度的不同月份之間進行比較,或與上一年度的相同月份進行比較,所以可以使用範圍分區。每個範圍的邊界都是按月份確定的。

按照圖 11 描述的步驟,使用基於 OrderDate 的範圍分區對錶進行分區。瞭解這臺新服務器的要求後,分析人員打算收集和分析連續六個月的數據,或當前年度與上一年度三個月份(例如 2003 年 1 月到 3 月與 2004 年 1 月到 3 月)的數據。要使磁盤分區最大化並隔離大多數數據組,多個文件組將使用相同的物理磁盤,但是這些文件組將相差六個月以減少磁盤爭用。當前數據是 2004 年 10 月,而所有 283 個存儲位置都在本地管理其當前銷售。服務器上存儲了從 2002 年 10 月到 2004 年 9 月的數據。爲了利用新的 16 向多處理器計算機和存儲區域網絡,每個月的文件存儲在一個文件組中,同時位於一個分區鏡像 (RAID 1+0) 磁盤集上。對於數據通過文件組在邏輯驅動器上的物理佈局,下圖(圖 12)描述了每月數據的位置。

ms345146.sql2k5partition_12(zh-cn,SQL.90).gif

圖 12 :分區表的順序

12 個邏輯驅動器都位於 RAID 1+0 配置中,因此 OrdersOrderDetails 數據所需的總磁盤數爲 48 個。存儲區域網絡支持 78 個磁盤,而另外 30 個用於事務日誌、TempDB、系統數據庫和其他更小的表,例如 Customers(900 萬)和 Products(386,750 行)。OrdersOrderDetails 表都使用相同的邊界條件、磁盤位置和分區架構。結果是(只看圖 13 中的兩個邏輯驅動器 [驅動器 E:\ 和 F:\]),相同月份的 OrdersOrderDetails 的數據都存儲在相同的磁盤上:

ms345146.sql2k5partition_13(zh-cn,SQL.90).gif

圖 13 :磁盤陣列上盤區位置的範圍分區

雖然看起來很複雜,但創建過程非常簡單。設計分區表最難的部分在於從大量數據源傳輸數據,即 283 個存儲位置都必須使用一種標準的傳輸機制。但是,中央服務器上只定義了一個 Orders 表和一個 OrderDetails 表。要將兩個表都創建爲分區表,請先創建分區函數和分區架構。分區架構定義分區在磁盤上的物理位置,因此必須存在文件組。在此表中,文件組是必需的,因此下一步是創建文件組。每個文件組的語法都與下面的語法相同,但必須創建所有 24 個文件組。有關創建所有 24 個文件組的完整腳本,請參見 RangeCaseStudyFilegroups.sql 腳本。

注意:如果沒有指定相應的驅動器號,將無法運行此腳本;但是此腳本包含一個“setup”表,可以修改此表以簡化測試。您可以將驅動器號/位置更改爲一個驅動器,以測試和學習語法。同時,確保將文件大小調整爲 MB 而不是 GB,並根據可用的磁盤空間考慮指定一個較小的初始大小。

將爲 SalesDB 數據庫創建 24 個文件和文件組。每個文件和文件組都具有相同的語法,只是位置、文件名和文件組名不相同:

ALTER DATABASE SalesDB    
ADD FILE      
(NAME = N'SalesDBFG1File1',
FILENAME = N'E:\SalesDB\SalesDBFG1File1.ndf',
SIZE = 20GB,
MAXSIZE = 35GB,
FILEGROWTH = 5GB) 
TO FILEGROUP [FG1]
GO

創建所有 24 個文件和文件組後,即可定義分區函數和分區架構。要驗證文件和文件組,請分別使用 sp_helpfile 和 sp_helpfilegroup。

分區函數將在 OrderDate 列中進行定義。使用的數據類型爲 datetime,而且兩個表都需要存儲 OrderDate 才能根據此值對兩個表進行分區。實際上,如果根據相同的鍵值對兩個表進行分區,則分區鍵值屬於重複信息,但它對於獲得對齊優點又是必需的。而且,在大多數情況下,應該是一個相當窄的列(datetime 數據類型爲 8 個字節)。如本文前面的“爲範圍分區創建分區函數”部分所述,此函數將是一個範圍分區函數,其中的第一個邊界條件位於 LEFT(第一個)分區中。

CREATE PARTITION FUNCTION TwoYearDateRangePFN(datetime)
AS
RANGE LEFT FOR VALUES ('20021031 23:59:59.997',      -- 2002 年 10 月
'20021130 23:59:59.997',   -- 2002 年 11 月
'20021231 23:59:59.997',   -- 2002 年 12 月
'20030131 23:59:59.997',   -- 2003 年 1 月
'20030228 23:59:59.997',   -- 2003 年 2 月
'20030331 23:59:59.997',   -- 2003 年 3 月
'20030430 23:59:59.997',   -- 2003 年 4 月
'20030531 23:59:59.997',   -- 2003 年 5 月
'20030630 23:59:59.997',   -- 2003 年 6 月
'20030731 23:59:59.997',   -- 2003 年 7 月
'20030831 23:59:59.997',   -- 2003 年 8 月
'20030930 23:59:59.997',   -- 2003 年 9 月
'20031031 23:59:59.997',   -- 2003 年 10 月
'20031130 23:59:59.997',   -- 2003 年 11 月
'20031231 23:59:59.997',   -- 2003 年 12 月
'20040131 23:59:59.997',   -- 2004 年 1 月
'20040229 23:59:59.997',   -- 2004 年 2 月
'20040331 23:59:59.997',   -- 2004 年 3 月
'20040430 23:59:59.997',   -- 2004 年 4 月
'20040531 23:59:59.997',   -- 2004 年 5 月
'20040630 23:59:59.997',   -- 2004 年 6 月
'20040731 23:59:59.997',   -- 2004 年 7 月
'20040831 23:59:59.997',   -- 2004 年 8 月
'20040930 23:59:59.997')   -- 2004 年 9 月
GO

因爲包含了最左側和最右側的邊界情況,所以此分區函數將創建 25 個分區。該表將保留第 25 個分區爲空白。不需要爲這個空分區指定特殊的文件組(因爲其中永遠不會包含數據)作爲限制表數據的約束。要將數據定向至相應的磁盤,可以使用分區架構將分區映射到文件組。分區架構將爲 24 個將要包含數據的文件組使用明確的文件組名,而爲第 25 個空分區使用 PRIMARY 文件組。

CREATE PARTITION SCHEME [TwoYearDateRangePScheme]
AS
PARTITION TwoYearDateRangePFN TO 
( [FG1], [FG2], [FG3], [FG4], [FG5], [FG6], 
[FG7], [FG8], [FG9], [FG10],[FG11],[FG12],
[FG13],[FG14],[FG15],[FG16],[FG17],[FG18],
[FG19],[FG20],[FG21],[FG22],[FG23],[FG24], 
[PRIMARY] )
GO

通過使用默認的文件組或用戶定義的文件組作爲未分區的表,或者使用架構創建分區表,可以使用與以前的版本支持的相同語法創建表。哪種方法更好取決於表的填充方式和創建的分區數。從性能角度看,先填充堆再建立羣集索引可能要勝過在已經建立索引的表中加載數據。另外,如果有多個 CPU,您可以通過並行 BULK INSERT 語句將數據加載到表中,然後也以並行方式建立索引。對於 Orders 表,按照正常的方式創建表,然後通過 INSERT SELECT 語句(從 AdventureWorks 示例數據庫中提取數據)加載現有的數據。要將 Orders 表建爲分區表,請在該表的 ON 子句中指定分區架構。Orders 表是使用以下語法創建的:

CREATE TABLE SalesDB.[dbo].[Orders]  
(
[PurchaseOrderID] [int] NOT NULL,
[EmployeeID] [int] NULL,
[VendorID] [int] NULL,
[TaxAmt] [money] NULL,
[Freight] [money] NULL,
[SubTotal] [money] NULL,
[Status] [tinyint] NOT NULL,
[RevisionNumber] [tinyint] NULL,
[ModifiedDate] [datetime] NULL,
[ShipMethodID]   tinyint NULL,
[ShipDate] [datetime] NOT NULL, 
[OrderDate] [datetime] NULL
CONSTRAINT OrdersRangeYear
CHECK ([OrderDate] >= '20021001' 
AND [OrderDate] < '20041001'), 
[TotalDue] [money] NULL
) ON TwoYearDateRangePScheme(OrderDate)
GO

因爲 OrderDetails 表也將使用此架構,而且必須包含 OrderDate,所以使用以下語法創建 OrderDetails 表:

CREATE TABLE [dbo].[OrderDetails](
[OrderID] [int] NOT NULL,
[LineNumber] [smallint] NOT NULL,
[ProductID] [int] NULL,
[UnitPrice] [money] NULL,
[OrderQty] [smallint] NULL,
[ReceivedQty] [float] NULL,
[RejectedQty] [float] NULL,
[OrderDate] [datetime] NOT NULL
CONSTRAINT OrderDetailsRangeYearCK
CHECK ([OrderDate] >= '20021001' 
AND [OrderDate] < '20041001'), 
[DueDate] [datetime] NULL,
[ModifiedDate] [datetime] NOT NULL 
CONSTRAINT [OrderDetailsModifiedDateDFLT] 
DEFAULT (getdate()),
[LineTotal]  AS (([UnitPrice]*[OrderQty])),
[StockedQty]  AS (([ReceivedQty]-[RejectedQty]))
) ON TwoYearDateRangePScheme(OrderDate)
GO

加載數據的下一步是通過兩個 INSERT 語句處理的。這兩個語句使用新的 AdventureWorks 數據庫(從中複製數據)。請安裝 AdventureWorks 示例數據庫以複製此數據:

INSERT dbo.[Orders]
SELECT o.[PurchaseOrderID] 
, o.[EmployeeID]
, o.[VendorID]
, o.[TaxAmt]
, o.[Freight] 
, o.[SubTotal] 
, o.[Status] 
, o.[RevisionNumber] 
, o.[ModifiedDate] 
, o.[ShipMethodID] 
, o.[ShipDate] 
, o.[OrderDate] 
, o.[TotalDue] 
FROM AdventureWorks.Purchasing.PurchaseOrderHeader AS o
WHERE ([OrderDate] >= '20021001'
AND [OrderDate] < '20041001')
GO
INSERT dbo.[OrderDetails]
SELECT    od.PurchaseOrderID
, od.LineNumber
, od.ProductID
, od.UnitPrice
, od.OrderQty
, od.ReceivedQty
, od.RejectedQty
, o.OrderDate
, od.DueDate
, od.ModifiedDate
FROM AdventureWorks.Purchasing.PurchaseOrderDetail AS od
JOIN AdventureWorks.Purchasing.PurchaseOrderHeader AS o
ON o.PurchaseOrderID = od.PurchaseOrderID
WHERE (o.[OrderDate] >= '20021001' 
AND o.[OrderDate] < '20041001')
GO

現在,數據已加載到分區表中,您可以使用新的內置系統函數來確定數據所在的分區。下面的查詢很有用,因爲它將返回包含數據的每個分區的以下信息:每個分區內存在的行數以及最小和最大 OrderDate。此查詢不會返回不包含行的分區。

SELECT $partition.TwoYearDateRangePFN(o.OrderDate) 
AS [Partition Number]
, min(o.OrderDate) AS [Min Order Date]
, max(o.OrderDate) AS [Max Order Date]
, count(*) AS [Rows In Partition]
FROM dbo.Orders AS o
GROUP BY $partition.TwoYearDateRangePFN(o.OrderDate)
ORDER BY [Partition Number]
GO
SELECT $partition.TwoYearDateRangePFN(od.OrderDate) 
AS [Partition Number]
, min(od.OrderDate) AS [Min Order Date]
, max(od.OrderDate) AS [Max Order Date]
, count(*) AS [Rows In Partition]
FROM dbo.OrderDetails AS od
GROUP BY $partition.TwoYearDateRangePFN(od.OrderDate)
ORDER BY [Partition Number]
GO

最後,在填充表後,可以建立羣集索引。在本例中,羣集索引將根據主鍵進行定義,因爲分區鍵標識兩個表(對於 OrderDetails,在索引中添加 LineNumber 以確保唯一性)。爲分區表建立索引的默認行爲是將索引與同一架構中的分區表對齊,而該架構是不需要指定的。

ALTER TABLE Orders
ADD CONSTRAINT OrdersPK
PRIMARY KEY CLUSTERED (OrderDate, OrderID)
GO
ALTER TABLE dbo.OrderDetails
ADD CONSTRAINT OrderDetailsPK
PRIMARY KEY CLUSTERED (OrderDate, OrderID, LineNumber)
GO

指定分區架構的完整語法如下:

ALTER TABLE Orders
ADD CONSTRAINT OrdersPK
PRIMARY KEY CLUSTERED (OrderDate, OrderID)
ON TwoYearDateRangePScheme(OrderDate)
GO
ALTER TABLE dbo.OrderDetails
ADD CONSTRAINT OrderDetailsPK
PRIMARY KEY CLUSTERED (OrderDate, OrderID, LineNumber)
ON TwoYearDateRangePScheme(OrderDate)
GO

連接分區表

連接對齊的表時,SQL Server 2005 提供了通過一個或多個步驟連接表的選項,通過此選項,可以先連接各個分區,然後將子集加起來。不管如何連接分區,SQL Server 都會評估是否可以實現某種程度的分區消除。

分區消除

在下面的查詢中,數據是從上一個方案中創建的 OrdersOrderDetails 表中查詢的。該查詢將只返回第三個季度的信息。通常,第三個季度包含訂單處理較慢的月份,但在 2004 年,這些月份是訂單最多的一些月份。在本例中,我們關心的是第三季度的 Products 趨勢(訂購的數量及其訂單日期)。爲了確保連接對齊的分區表時能夠受益於分區消除,必須指定每個表的分區範圍。在本例中,因爲 Orders 表的主鍵是 OrderDateOrderID 的組合鍵,這些表之間的連接顯示錶之間的 OrderDate 必須相等。SARG(搜索參數)將應用於兩個分區表。檢索此數據的查詢如下:

SELECT o.OrderID, o.OrderDate, o.VendorID, od.ProductID, od.OrderQty
FROM dbo.Orders AS o
INNER JOIN dbo.OrderDetails AS od 
ON o.OrderID = od.OrderID
AND o.OrderDate = od.OrderDate
WHERE o.OrderDate >= '20040701' 
AND o.OrderDate <= '20040930 11:59:59.997'
GO

如圖 14 所示,查看實際或預測的示例輸出時,要查看一些關鍵元素:首先(使用 SQL Server Management Studio),將光標懸停在所訪問的表上時,您會看到“Estimated Number of Executions”或“Number of Executions”。在本例中,可以看到一個季度或三個月的數據。每個月都有自己的分區,而且查看此數據時可以看到執行了三次:每個表一次。

ms345146.sql2k5partition_14(zh-cn,SQL.90).gif

圖 14 :執行次數

如圖 15 所示,SQL Server 正在消除所有不需要的分區,並且只選擇包含正確數據的分區。請查看“Argument”部分中的 PARTITION ID:([PtnIds1017]),瞭解正在評估的內容。您可能想知道“PtnIds1017”表達式是從哪裏來的。這是此查詢中訪問的分區的邏輯表示。如果您將光標懸停在示例頂部的“Constant Scan”上,您會發現它顯示了參數 VALUES(((21)), ((22)), ((23)))。這代表分區號。

ms345146.sql2k5partition_15(zh-cn,SQL.90).gif

圖 15 :分區消除

要驗證每個分區並且只驗證這些分區中存在的數據,請使用前面使用的查詢(經過稍微修改)訪問分區的新的內置系統函數:

SELECT $partition.TwoYearDateRangePFN(o.OrderDate) 
AS [Partition Number]
, min(o.OrderDate) AS [Min Order Date]
, max(o.OrderDate) AS [Max Order Date]
, count(*) AS [Rows In Partition]
FROM dbo.Orders AS o
WHERE $partition.TwoYearDateRangePFN(o.OrderDate) IN (21, 22, 23)
GROUP BY $partition.TwoYearDateRangePFN(o.OrderDate)
ORDER BY [Partition Number]
GO

此時,您可以從圖形上識別分區消除。可以對分區表和索引使用其他的優化方法,尤其是在它們與您要連接的表對齊的情況下。SQL Server 可以通過先連接每個分區來執行多個連接。

預先連接對齊的表

在同一個查詢中,SQL Server 不僅消除分區,還分別在其餘分區之間執行連接。除了查看每個表訪問的執行次數之外,請注意與合併連接相關的信息。如果將光標懸停在合併連接的上方,您會發現合併連接執行了三次。

ms345146.sql2k5partition_16(zh-cn,SQL.90).gif

圖 16 :連接分區表

在圖 16 中,請注意執行了額外的嵌套環連接。看上去這是在合併連接後發生的,但實際上,分區 ID 已經傳遞給每個表搜索或掃描操作;最後這個連接只是將兩個分區數據集連接起來,確保每個數據集都符合一開始(在“Constant Scan”表達式中)定義的分區 ID。

滑動窗口方案

當下一個月的數據(在本例中是 2004 年 10 月)可用時,將按特定的操作順序使用現有的文件組、移入和移出數據。而在本銷售方案中,目前 FG1 中的數據是 2002 年 10 月的數據。現在 2004 年 10 月的數據是可用的,因此,根據可用空間和存檔要求,您有兩個選擇。記住,要將分區從表中快速移入或移出,移動操作必須只更改元數據。特別是,必須在要移入或移出的同一個文件組中創建新表(源或目標,即僞造的分區)。如果您打算繼續使用相同的文件組(本例中爲 FG1),則需要確定如何滿足空間和存檔要求。當表中沒有完整的兩個年度的數據時,爲了最大程度地縮短時間,並且如果擁有足夠的空間,您可以將當前數據(2004 年 10 月)加載到 FG1 中,而無需刪除要存檔的數據(2002 年 10 月)。但是,如果沒有足夠的空間同時保留當前月份和要存檔的月份,則需要先移出舊的分區(然後再刪除它)。

不管怎樣,存檔應該很容易,並且可能已經完成。好的存檔做法是,加載和移入新分區之後立即備份文件組,而不要等到打算移出分區時再進行備份。例如,如果 RAID 陣列出現故障,則可以恢復文件組,而無需重新生成或重新加載數據。具體到本例中,因爲數據庫是最近才分區的,所以您可能已經在分區結構穩定後執行了完整的備份。當然,完整的數據庫備份並非唯一的選擇。在 SQL Server 2005 中可以實現各種各樣的備份策略,而且許多備份策略都可以爲備份和恢復提供更好的準確性。因爲這麼多的數據都是不變的,所以您可以在加載後備份各個文件組。實際上,這應該是滾動分區策略的一部分。有關詳細信息,請參見 SQL Server Books Online的“Administering SQL Server”中的“File and Filegroup Backups”部分。

現在,策略已經就位,您需要了解確切的處理過程和語法。語法和步驟數可能看起來很複雜,但每個月的處理過程都是相同的。通過使用動態 SQL 執行,您可以按照以下步驟輕鬆地使此過程自動化:

  • 管理將要移入的分區的分段表。

  • 管理將要移出的分區的第二個分段表。

  • 將舊數據移出分區表,並將新數據移入分區表。

  • 刪除分段表。

  • 備份文件組。

後面各節詳細介紹了每個步驟的語法和最佳做法,還提供了註釋,以幫助您通過動態 SQL 執行使此過程自動化。

管理將要移入的分區的分段表

  1. 創建分段表(將來的僞造分區)。這個分段表必須有一個約束,將其數據限制爲只對要創建的分區有效的數據。爲了獲取更好的性能,將數據加載到未建立索引且未應用約束的堆中,然後在將表移入分區表之前添加約束(參見步驟 3)WITH CHECK。

    CREATE TABLE SalesDB.[dbo].[OrdersOctober2004]  
    (
    [OrderID] [int] NOT NULL,
    [EmployeeID] [int] NULL,
    [VendorID] [int] NULL,
    [TaxAmt] [money] NULL,
    [Freight] [money] NULL,
    [SubTotal] [money] NULL,
    [Status] [tinyint] NOT NULL,
    [RevisionNumber] [tinyint] NULL,
    [ModifiedDate] [datetime] NULL,
    [ShipMethodID] [tinyint] NULL,
    [ShipDate] [datetime] NOT NULL, 
    [OrderDate] [datetime] NOT NULL, 
    [TotalDue] [money] NULL
    ) ON [FG1]
    GO
    

    在自動化過程中:此表很容易創建,因爲它總是代表當前月份。根據進程運行的時間,使用 DATENAME(m, getdate()) 等內置函數檢測月份是很容易的。因爲表的結構必須與現有表相匹配,所以每個月的主要變動是表名稱。但是,您可以爲每個月使用相同的名稱,因爲將表添加到分區中之後,表即不需要再存在。雖然將數據移入分區表後該表仍然存在,但您可以在移動操作完成後刪除分段表。另外,必須更改日期範圍。因爲您要處理的是 datetime 數據,而在時間的存儲方式方面又存在舍入問題,所以必須能夠通過編程方式確定正確的毫秒值。要確定月末最後的 datetime 值,最容易的方法是將正在處理的月份加上 1 個月,然後再減去 2 或 3 毫秒。不能只減去 1 毫秒,因爲 59.999 會上舍入爲 .000,即下個月的第一天。可以減去 2 或 3 毫秒,因爲 2 毫秒將向下舍入爲 .997,而 3 毫秒等於 .997;.997 是可以存儲的有效值。這樣即可確定 datetime 範圍的正確結束值:

    DECLARE @Month            nchar(2),
    @Year            nchar(4),
    @StagingDateRange      nchar(10)
    SELECT @Month = N'11', @Year = N'2004'
    SELECT @StagingDateRange = @Year + @Month + N'01'
    SELECT dateadd(ms, -2, @StagingDateRange)
    

    每個月會重新創建表,因爲它需要保留在要移入和移出數據的文件組中。要確定要處理的相應文件組,請將以下系統表查詢與前面介紹的 $partition 函數結合使用。指定要移出的範圍內的任何日期。這是要在其中執行所有操作的分區和文件組。帶有下劃線的部分需要針對特定的表、分區函數和特定的日期進行更改。

    SELECT ps.name AS PSName, 
    dds.destination_id AS PartitionNumber, 
    fg.name AS FileGroupName
    FROM (((sys.tables AS t 
    INNER JOIN sys.indexes AS i 
    ON (t.object_id = i.object_id))
    INNER JOIN sys.partition_schemes AS ps 
    ON (i.data_space_id = ps.data_space_id))
    INNER JOIN sys.destination_data_spaces AS dds 
    ON (ps.data_space_id = dds.partition_scheme_id))
    INNER JOIN sys.filegroups AS fg
    ON dds.data_space_id = fg.data_space_id
    WHERE (t.name = 'Orders') AND (i.index_id IN (0,1)) AND
    dds.destination_id = $partition.TwoYearDateRangePFN('20021001') 
    
  2. 加載包含數據的分段表。如果文件是一致的,此過程應該通過 BULK INSERT 語句執行。

    在自動化過程中:這是自動化過程最複雜的部分。您需要確保所有文件都已經加載,還應考慮並行加載這些文件。跟蹤加載了哪些文件以及文件位置的表可以幫助您控制此過程。您可以創建一個 SQL Agent 作業,每隔幾分鐘檢查一次文件,拾取新文件並執行多個 BULK INSERT 語句。

  3. 加載數據後,即可添加約束。爲了使數據可信,必須添加約束 WITH CHECK。WITH CHECK 設置是默認的,因此不需要指定,但一定不能設置爲 WITH NOCHECK。

  4. 爲分段表建立索引。分段表必須與其要移入的表(成爲該表的一個分區)具有相同的羣集索引。

    ALTER TABLE [OrdersOctober2004]
    ADD CONSTRAINT OrdersOctober2004PK 
    PRIMARY KEY CLUSTERED (OrderDate, OrderID)
    ON [FG1]
    GO
    

    在自動化過程中:這是一個非常容易的步驟。使用步驟 1 中的月份和文件組信息,可以創建此羣集索引。

    ALTER TABLE SalesDB.[dbo].[OrdersOctober2004]  
    WITH CHECK
    ADD CONSTRAINT OrdersRangeYearCK
    CHECK ([OrderDate] >= '20041001' 
    AND [OrderDate] <= '20041031 23:59:59.997')
    GO
    

管理將要移出的分區的第二個分段表。

  1. 創建第二個分段表。這是一個空表,用於存儲移出的分區中的數據。

    CREATE TABLE SalesDB.[dbo].[OrdersOctober2002]  
    (
    [OrderID] [int] NOT NULL,
    [EmployeeID] [int] NULL,
    [VendorID] [int] NULL,
    [TaxAmt] [money] NULL,
    [Freight] [money] NULL,
    [SubTotal] [money] NULL,
    [Status] [tinyint] NOT NULL,
    [RevisionNumber] [tinyint] NULL,
    [ModifiedDate] [datetime] NULL,
    [ShipMethodID] [tinyint] NULL,
    [ShipDate] [datetime] NOT NULL, 
    [OrderDate] [datetime] NOT NULL, 
    [TotalDue] [money] NULL
    ) ON [FG1]
    GO
    
  2. 爲分段表建立索引。分段表必須與其要移入的表(成爲該表的一個分區,而該分區將成爲此表)具有相同的羣集索引。

    ALTER TABLE [OrdersOctober2002]
    ADD CONSTRAINT OrdersOctober2002PK 
    PRIMARY KEY CLUSTERED (OrderDate, OrderID)
    ON [FG1]
    GO
    

將舊數據移出分區表,並將新數據移入分區表

  1. 移出舊數據,放入第二個分段表中。

    ALTER TABLE Orders
    SWITCH PARTITION 1
    TO OrdersOctober2002
    GO
    
  2. 更改分區函數以刪除 2002 年 10 月的邊界點。

    ALTER PARTITION FUNCTION TwoYearDateRangePFN()
    MERGE RANGE ('20021031 23:59:59.997')
    GO
    
  3. 此操作還會刪除文件組與分區架構之間的關聯。具體來說,FG1 將不再是分區架構的一部分。因爲您將滾動相同的現有 24 個分區的新數據,所以需要使 FG1 成爲“下一個使用的”分區,此分區將是下一個用於拆分的分區。

    ALTER PARTITION SCHEME TwoYearDateRangePScheme 
    NEXT USED [FG1]
    GO
    
  4. 更改分區函數,爲 2004 年 10 月添加新的邊界點。

    ALTER PARTITION FUNCTION TwoYearDateRangePFN() 
    SPLIT RANGE ('20041031 23:59:59.997')
    GO
    
  5. 更改基礎表的約束定義(如果存在),以允許新範圍的數據。因爲添加約束的代價可能很昂貴(需要驗證數據),所以最好的做法是繼續擴大日期範圍,而不是刪除並重新創建約束。現在,只存在一個約束 (OrdersRangeYearCK),但以後將存在兩個約束。

    ALTER TABLE Orders
    ADD CONSTRAINT OrdersRangeMaxOctober2004
    CHECK ([OrderDate] < '20041101')
    GO
    ALTER TABLE Orders
    ADD CONSTRAINT OrdersRangeMinNovember2002
    CHECK ([OrderDate] >= '20021101')
    GO
    ALTER TABLE Orders
    DROP CONSTRAINT OrdersRangeYearCK
    GO
    
  6. 從第一個分段表中移入新數據。

    ALTER TABLE OrdersOctober2004
    SWITCH TO Orders PARTITION 24
    GO
    

刪除分段表

因爲下一個步驟(也是最後一個步驟)將存檔所有數據,所以不再需要分段數據。刪除表是最快的方式。

DROP TABLE dbo.OrdersOctober2002
GO
DROP TABLE dbo.OrdersOctober2004
GO

備份文件組

最後一步備份的對象是根據您的備份策略選擇的。如果選擇了基於文件或文件組的備份策略,則應執行文件或文件組備份。如果選擇了基於整個數據庫的備份策略,則可以執行完整數據庫備份或差異備份。

BACKUP DATABASE SalesDB 
FILEGROUP = 'FG1' 
TO DISK = 'C:\SalesDB\SalesDB.bak'
GO

列表分區:地區數據

如果您的表包含的數據來自多個地區,而通常只對一個地區的數據進行分析,或者定期從每個地區接收數據,請考慮以列表的形式使用已定義的範圍分區。換句話說,就是使用函數將每個分區定義爲一個地區值。例如,有一家西班牙的公司,它的客戶分佈在西班牙、法國、德國、意大利和英國。該公司的銷售數據總是按國家進行分析。該公司的表可以擁有 5 個分區,每個國家一個分區。

這樣一個列表分區的創建過程與日期的範圍分區幾乎完全相同,不同之處在於,除了實際的分區鍵外,該範圍的邊界沒有任何其他值。實際上,它是一個列表,而不是範圍。儘管它是一個列表,但邊界條件必須包含最左側和最右側。要創建 5 個分區,只需在分區函數中指定 4 個值。不需要爲這些值排序(SQL Server 將在內部爲它們排序),但是爲了獲得正確的分區數,最符合邏輯的方法是對分區值進行排序,將最大值指定給最後一個分區(定義爲 LEFT 分區函數時),或者對分區值進行排序,並從倒數第二個值開始(對於 RIGHT)。

因爲有 5 個分區,所以必須有 5 個文件組。在本例中,這些文件組根據存儲的數據命名。腳本文件 RegionalRangeCaseStudyFilegroups.sql 充分顯示了此語法。每個文件組都可以使用相同的設置進行創建,但如果數據不平衡,則不必這麼做。只顯示了西班牙的文件組和文件;其他四個文件組和文件中都具有相同的參數,但位於不同的驅動器上,而且具有特定於國家分區的名稱。

ALTER DATABASE SalesDB
ADD FILEGROUP [Spain]
GO
ALTER DATABASE SalesDB    
ADD FILE      
(NAME = N'SalesDBSpain',
FILENAME = N'C:\SalesDB\SalesDBSpain.ndf',
SIZE = 1MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB) 
TO FILEGROUP [Spain]
GO

下一步是創建函數,該函數將指定只有四個分區使用 LEFT 作爲邊界條件。在本例中,列表將包括除英國以外的所有國家,因爲英國在按字母順序排列的列表中位於最後。

CREATE PARTITION FUNCTION CustomersCountryPFN(char(7))
AS
RANGE LEFT FOR VALUES ('France', 'Germany', 'Italy', 'Spain')
GO

要將數據放入根據數據命名的文件組中,分區架構將按字母順序列出。所有五個文件組都必須在分區架構的語法中指定。

CREATE PARTITION SCHEME [CustomersCountryPScheme]
AS
PARTITION CustomersCountryPFN 
TO ([France], [Germany], [Italy], [Spain], [UK])
GO

最後,可以在新的 CustomersCountryPScheme 中創建 Customers 表。

CREATE TABLE [dbo].[Customers](
[CustomerID] [nchar](5) NOT NULL,
[CompanyName] [nvarchar](40) NOT NULL,
[ContactName] [nvarchar](30) NULL,
[ContactTitle] [nvarchar](30) NULL,
[Address] [nvarchar](60) NULL,
[City] [nvarchar](15) NULL,
[Region] [nvarchar](15) NULL,
[PostalCode] [nvarchar](10) NULL,
[Country] [char](7) NOT NULL,
[Phone] [nvarchar](24) NULL,
[Fax] [nvarchar](24) NULL
) ON CustomersCountryPScheme (Country)
GO

儘管範圍分區被定義爲只支持範圍,但它們還爲執行其他類型的分區(例如列表分區)提供了一種方法。

 

總結

使用 SQL Server 2005,您可以通過分區輕鬆一致地管理大量表和索引,從而使您可以在活動表之外管理數據子集。這提供了簡化的管理、改善的性能以及抽象的應用程序邏輯,因爲分區架構對於應用程序是完全透明的。如果您的數據具有邏輯分組(範圍或列表),而大量查詢必須分析這些預定義的、一致的範圍內的數據,還需要管理這些預定義範圍內的傳入數據和傳出數據,則範圍分區是簡單的選擇。如果您查看對大量數據進行的分析(沒有使用特定範圍),或者所有查詢都訪問大多數數據(如果不是所有數據),那麼使用多個沒有任何特定放置方法的文件組是一種更容易的解決方案,此解決方案還可以改善性能。

本文的腳本

本白皮書代碼示例中使用的腳本可以從 SQLServer2005PartitionedTables.zip 文件中找到。下面介紹了該壓縮文件中的每個文件。

RangeCaseStudyScript1-Filegroups.sql - 包括用於創建範圍分區表案例研究所需的文件組和文件的語法。此腳本是可以修改的,是您可以在更小的磁盤集上使用更小的文件(以 MB 而不是 GB 爲單位)創建此示例。此外,它還包含通過 INSERT...SELECT 語句導入數據的代碼,使您可以通過相應的分區函數推測數據的位置。

RangeCaseStudyScript2-PartitionedTable.sql - 包括用於創建與範圍分區表案例研究相關的分區函數、分區架構和範圍分區表的語法。此腳本還包含相應的約束和索引。

RangeCaseStudyScript3-JoiningAlignedTables.sql - 包括說明 SQL Server 爲分區表提供的各種連接策略的查詢。

RangeCaseStudyScript4-SlidingWindow.sql - 包括與範圍分區表案例研究中按月進行管理有關的語法和過程。在此腳本中,您將在 Orders 表中移入和移出數據。您還可以自行決定是否創建相同的過程,以便在 OrderDetails 表中移入和移出數據。提示:請參見 RangeCaseStudyScript2 中爲 OrderDetails 插入表和正確數據列而使用的 Insert 語句。

RegionalRangeCaseStudyFilegroups.sql - 包括用於創建地區性分區表案例研究所需的文件組和文件的語法。實際上,這是一個模擬列表分區架構的範圍分區。

RegionalRangeCaseStudyPartitionedTable.sql - 包括用於創建與範圍分區表案例研究相關的分區函數、分區架構和地區性分區表的語法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章