Sql-Server

無法從現有分區 SQL Server 2014 創建/移動數據到新分區

  • June 29, 2017

我們有一個 SQL Server 2014 企業版和一個大小約為 6 TB 的數據庫。

只是為了提供基礎設施的快速背景,因為伺服器位於 Azure 中,並且有 9 TB 的高級磁碟用於數據文件。

有一些已經按標識符分區的大表(MonthlyDate 整數,例如 01012016,… 31122016 )。我們有從 2014 年到 2016 年的每月分區(01012014,01022014……直到 31122016)。

現在我們正在嘗試按月創建 2017 年和 2018 年的分區。

我嘗試使用分區嚮導,但找不到我想要的選項。據我所知,我需要執行類似:

Alter partition Scheme [PartPScheme_BIGTAB] Next Used [PartFileGrp_201701]

Alter partition Function [PartPFN_BIGTAB] () split range(20170131)

我曾嘗試多次執行 abrove 腳本,但它已經花費了 7 多個小時,只有 1 GB 的數據被移動到上面的分區,最後我們不得不回滾腳本。

我正在尋找有人為我指出正確的方向,以實現此類事情的最佳實踐。不太確定如何解決這個問題。

可能是什麼問題?

目前的分區函式為:

CREATE PARTITION FUNCTION [PartPFN_BIGTAB](int) AS RANGE LEFT FOR VALUES (
     20141031
   , 20141131
   , 20141231
   , 20150131
   , 20150231
   , 20150331
   , 20150431
   , 20150531
   , 20150631
   , 20150731
   , 20150831
   , 20150931
   , 20151031
   , 20151131
   , 20151231
   , 20160131
   , 20160231
   , 20160331
   , 20160431
   , 20160531
   , 20160631
   , 20160731
   , 20160831
   , 20160931
   , 20161031
   , 20161131
   , 20161231
   );

如果您打算按年/月對這些數據進行分區,我認為您目前的分區列(它是整數而不是“真實”日期數據類型,即使是整數也不是 yyyymmdd 格式)對於這項工作來說都是錯誤的. 我還假設您在表中沒有另一列是真正的 Date 數據類型中的 MonthlyDate。

在我看來(並假設您有額外的磁碟空間),您應該:

  • 創建一個使用DATE數據類型的新分區函式。建議應該這樣做RANGE RIGHT(有關解釋,請參閱此答案底部的 Dan Guzman 連結)。確保您創建的範圍遠低於您的最小日期以及遠高於您的最大日期的範圍。此外,隨著時間的推移,請確保您在拆分空分區之前遠遠早於已經填充其中的任何數據。
  • 創建一個引用新分區函式的新分區方案。
  • 通過編寫目前表的創建腳本來創建一個新的“替換”表(引用新創建的分區方案),但添加一個從整數 MonthlyDate 列派生/轉換的計算/持久 DATE 列(例如:PartitionedColumn DATE)。
  • 設置一個插入語句,將現有表中的記錄插入到新表中,例如在事務中批量插入幾千或十萬條記錄。事務完成後執行日誌備份(如果您不在 SIMPLE 恢復中)。這樣可以防止事務日誌空間不足。然後重複批處理…繼續這樣做,直到所有記錄都寫入具有持久計算列的新表。
  • 然後更改舊表名,將新表名更改為舊表名

請記住,參與分區方案的所有唯一索引必須將分區列定義為基本索引定義的一部分,而不僅僅是包含列。

此外,為了啟用分區切換(通常在“滑動視窗”中使用),表上的所有索引都必須對齊。BOL 對此有很好的資訊。尋找分區索引的特殊指南

最後,查看 Dan Guzman關於 Sql Server 分區的優秀文章。

您應該在年初之前創建了 2017 年的分區。因為現在您的最後一個分區包含從 2016 年 12 月 1 日到現在的所有數據。拆分時,必須將每一行物理移動到新分區。

參考:https ://docs.microsoft.com/en-us/sql/t-sql/statements/alter-partition-function-transact-sql

始終在分區範圍的兩端保留空分區,以保證分區拆分(載入新數據之前)和分區合併(解除安裝舊數據之後)不會引起任何數據移動。避免拆分或合併填充的分區。這可能是非常低效的,因為這可能會導致多達四倍的日誌生成,並且還可能導致嚴重的鎖定。

您可以採取幾種不同的方法來最大程度地減少 io 影響。我發現下面文章中描述的解決方案是最好的解決方案之一。它也是由微軟一流的現場工程師團隊編寫的。

糟糕……我忘了留下一個空的 SQL 表分區,如何在 IO 影響最小的情況下拆分它?

Kendra Little 的另一本好讀物,與您的情況有某種關係。

將分區添加到基於左的分區函式的下端

編輯:根據@ScottHodgin 的評論,您的分區列可能是整數數據類型,而不是日期時間或日期類型。您可能希望同時解決此問題。

引用自:https://dba.stackexchange.com/questions/177478