SQL Server 2005中處理表分區問題

數據庫性能調優是每一個優秀SQL Server管理員最終的責任。雖然保證數據的安全和可用性是我們的最高的目標,但是假如數據庫應用程序無法滿足用戶的要求,那麼DBA們會因爲性能低下的設計和實現而受到指責。SQL Server 2005在數據庫性能方面得到了很多提高,尤其是表分區的技術。如果你還沒不瞭解表分區的特徵,那麼請你花點時間讀這篇文章。

  表分區的概念不是一個新的概念;只要你當過一段時間的SQL Server DBA,那麼你可能已經對一些頻繁訪問的表進行過歸檔,當這個表中的歷史數據變的不再經常被訪問的時候。比如,假設你有一個打印時間報表的應用,你的報告很少會查詢1995年的數據,因爲絕大部分的預算規劃會基於最近幾年的數據。

  在SQL Server的早期版本中,你可以創建多個表。每一個表都具有相同的列結構,用來保存不同年份的數據。這樣,當存在着對歷史數據訪問的必要的時候,你可以創建一個視圖來對這些表進行查詢處理。將數據保存在多個表中是很方便的,因爲相對於查詢時掃描整個大表,掃描小表會更快。但是這種好處只有在你預先知道哪些時間段的數據會被訪問。同時,一旦數據過期,你還需要創建新表並且轉移新產生的歷史數據。

  SQL Server 7和SQL Server 2000支持分佈式分區視圖(distributed partitioned views,又稱爲物化視圖,materialized views).分佈式分區視圖由分佈於多臺服務器上的、具有相同表結構的表構成,而且你還需要爲每一個服務器增加鏈接服務器定義(linked server definitions),最後在其中一臺服務器上創建一個視圖將每臺服務器上返回的數據合併起來。這裏的設計思想是數據庫引擎可以利用多臺服務器的處理能力來滿足查詢。

  但是,分佈式分區視圖(DPV)受到很多限制,你可以在SQL Server的在線幫助文檔中閱讀到。雖然DPV在一些情況下能夠提供性能上的提高,但是這種技術不能被廣泛的應用。已經被證明它們不能滿足逐步增長的企業級應用的要求。何況,DPV的實現是一個費力的過程,需要DBA進行很多工作。

  SQL Server 2005開始支持表分區,這種技術允許所有的表分區都保存在同一臺服務器上。每一個表分區都和在某個文件組(filegroup)中的單個文件關聯。同樣的一個文件/文件組可以容納多個分區表。

  在這種設計架構下,數據庫引擎能夠判定查詢過程中應該訪問哪個分區,而不用掃描整個表。如果查詢需要的數據行分散在多個分區中,SQL Server使用多個處理器對多個分區進行並行查詢。你可以爲在創建表的時候就定義分區的索引。 對小索引的搜索或者掃描要比掃描整個表或者一張大表上的索引要快很多。因此,當對大表進行查詢,表分區可以產生相當大的性能提升。

  現在讓我們通過一個簡單的例子來了解表分區是如何發揮作用的。在這篇文章中,我不想深入到分區的語法細節當中,這些你可以在SQL Server的在線幫助文檔中找到。下面的例子基於存儲着一個時間報表系統的數據的數據倉庫。除了默認的文件組,我另外創建了7個文件組,每一個文件組僅包含一個文件,這個文件將存儲由分區函數定義的一部分數據。

  爲了測試表分區的性能提升,我向這個分區表中插入了一千五百萬行,同時向另外一個具有相同表結構、但是沒有進行分區的表插入了同樣的數據。對分區表執行的INSERT語句運行的更快一些。甚至在我的內存不到1G的筆記本電腦上,對分區表的INSERT語句比不分區的表的INSERT語句要快上三倍。當然,查詢的執行時間依據硬件資源的差異而所有變化,但是你還是能夠在你的環境中感到不同程度的提升。

  我將檢查更深入了一步,通過分別檢查同一條返回所有行的、簡單SELECT語句在分區表和非分區表上的執行計劃,返回的數據範圍通過WHERE語句來指定。同一條語句在這兩個不同的表上有不同的執行計劃。對於分區表的查詢顯示出一個嵌套的循環和索引的掃描。從本質上來說,SQL Server將兩個分區視爲獨立的表,因此使用一個嵌套循環將它們連接起來。對非分區的表的同一個查詢則使用索引掃描來返回同樣的列。當你使用同樣的分區策略創建多個表,同時在查詢中連接這些表,那麼性能上的提升會更加明顯

你可以使用下面的查詢來了解每一個分區中的行的個數:

  SELECT $PARTITION.TimeEntryDateRangePFN(time_entry_date) AS Partition,
  COUNT(*) AS [COUNT] FROM fact_time_entry
  GROUP BY $PARTITION.TimeEntryDateRangePFN(time_entry_date)
  ORDER BY Partition


  表分區對交易環境和數據倉庫環境來說,都是一個重要的特徵。數據倉庫用戶最主要的抱怨是移動事實表(fact table)會花費太多時間。當裝載數據到事實表的時候,用戶查詢(立方體處理查詢)的性能會明顯下降,甚至是完全無法成功。因此,裝載大量的數據到事實表的時候常常需要停機。如果使用表分區,就不再出現這樣的情況——確切的講,你一眨眼的工夫就可以移動事實表。爲了演示這是如何生效的,我使用上面例子中相同的分區函數和表結構來創建一個新的表,這個表叫做fact_time_entry2。表的主鍵從五千萬開始,這樣fact_time_entry2就不會包含表fact_time_entry中已經有的數據。

  現在我把2007年的數據移動到這張fact_time_entry2中。同時讓我們假設fact_time_entry表中包含着2007年之前的數據。在fact_time_entry2表完成數據的轉移,我執行下面的語句:

  ALTER TABLE fact_time_entry2
  SWITCH PARTITION 8 TO fact_time_entry PARTITION 8


  這條語句將編號爲8的分區,這個分區恰好包含着2007年的數據,從fact_time_entry2移動到了fact_time_entry表中,在我的筆記本電腦上,這個過程只花費了3毫秒。在這短短的3毫秒中,我的事實表就增加了五百萬條記錄!的確,我需要在交換分區之前,將數據移動到中間表,但是我的用戶不需要擔心——事實表隨時都可以查詢!在這幕後,實際上沒有數據移動——只是兩張表的元數據發生了變化。

  我可以使用類似的查詢刪除事實表中不在需要的數據。例如,假設我們決定我們不再關心2004年的記錄。下面的語句可以將這些記錄轉移到我們創建的工作表中:

  ALTER TABLE fact_time_entry
  SWITCH PARTITION 2 TO fact_time_entry2 PARTITION 2


  這樣的語句依舊在毫秒級內完成了。現在,我可以刪除fact_time_entry2或者將它移到其他的服務器上。我的事實表不會包含2004年的任何記錄。這個分區還是需要在目的表中存在,而且它必須是空的。你不能將分區轉移到一個包含重複數據的表中。源表和目的表的分區必須一致,同時被轉移的數據必須在同一個文件組中。即使受到這麼多的限制,轉換分區和無需停機就可以移動數據表的功能必將讓數據倉庫的實現變的前所未有的輕鬆。

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/long2006sky/archive/2007/05/08/1600931.aspx

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