分享方式:


使用 XMLA 端點進行累加式重新整理和即時資料

具有 XMLA 端點的 Premium 容量中的語意模型已啟用讀取/寫入作業,允許透過工具、指令碼和 API 支援進行更進階的重新整理、磁碟分割和僅中繼資料部署。 此外,透過 XMLA 端點進行的重新整理作業不限於每天 48 次重新整理,且不強制實施排程的重新整理使用時間限制

資料分割

語意模型表格磁碟分割不可見,而且無法使用 Power BI Desktop 或 Power BI 服務進行管理。 對於指派給 Premium 容量的工作區中的模型,可以使用 SQL Server Management Studio (SSMS)、開放原始碼表格式編輯器等工具,使用表格式模型指令碼語言 (TMSL) 編寫指令碼等工具透過 XMLA 端點來管理磁碟分割,並以程式設計方式使用表格式物件模型 (TOM)。

當您第一次將模型發佈到 Power BI 服務時,新模型中的每個表格都有一個磁碟分割。 對於沒有累加式重新整理原則的表格,該磁碟分割包含該表格的所有列,除非已套用篩選器。 對於具有累加式重新整理原則的表格,僅存一個初始磁碟分割,因為 Power BI 尚未套用該原則。 根據 RangeStartRangeEnd 參數以及 Power Query 編輯器中套用的任何其他篩選器定義您表格的日期/時間範圍篩選器時,您可以在 Power BI Desktop 中設定初始磁碟分割。 此初始磁碟分割僅包含符合您篩選準則的這些資料列。

當您執行第一次重新整理作業時,沒有累加式重新整理原則的表格會重新整理該表格的預設單一磁碟分割中包含的所有列。 對於具有累加式重新整理原則的表格,會自動建立重新整理分區和歷史磁碟分割,並根據每列的日期/時間將列載入到其中。 如果累加式重新整理原則包括即時取得資料,Power BI 也會在表格中新增 DirectQuery 磁碟分割。

第一次重新整理作業可能需要相當長的時間,具體取決於需要從資料來源載入的資料量。 模型的複雜性也可能是重要因素,因為重新整理作業必須進行更多處理和重新計算。 這項作業可以啟動。 如需詳細資訊,請參閱防止初始完整重新整理逾時

磁碟分割是按週期細微性而建立及命名:年、季、月和日。 最近的磁碟分割 (重新整理磁碟分割) 包含您在原則中指定的重新整理週期內的列。 歷史磁碟分割包含以完整週期到重新整理週期的列。 如果啟用即時,DirectQuery 磁碟分割會挑選重新整理週期結束日期之後發生的任何資料變更。 重新整理和歷史磁碟分割的細微性取決於您在定義原則時選擇的重新整理和歷史 (儲存) 週期。

例如,如果今天的日期是 2021 年 2 月 2 日,並且我們在資料來源中的 FactInternetSales 表格包含截至今天的列,如果我們的原則指定包含即時變更,則重新整理最後一天重新整理期間的列,並且儲存過去三年歷史期間的列。 然後,透過第一次重新整理作業,為未來的變更建立 DirectQuery 磁碟分割,為今天的列建立新的匯入磁碟分割,為昨天 (2021 年 2 月 1 日一整天期間) 建立歷史磁碟分割。 為上一整月期間 (2021 年 1 月) 建立歷史磁碟分割,為上一整年期間 (2020 年) 建立歷史磁碟分割,並且建立 2019 年和 2018 年全年的歷史磁碟分割。 由於我們尚未完成 2021 年第一個完整季度,因此未建立整個季度磁碟分割。

圖表顯示文字中所述的磁碟分割命名細微性。

每次重新整理作業時,僅重新整理重新整理週期磁碟分割,並且更新 DirectQuery 磁碟分割的日期篩選器以僅包含目前重新整理週期之後發生的變更。 在更新的重新整理週期內為具有新日期/時間的新列建立新的重新整理磁碟分割,並透過更新重新整理具有重新整理週期中現有磁碟分割的日期/時間的現有列。 將不再重新整理日期/時間早於重新整理週期的列。

當整個週期結束時,系統會合併磁碟分割。 例如,如果原則中指定一天的重新整理週期和三年的歷史儲存週期,則在該月的第一天,上個月的所有日磁碟分割都會合併為月磁碟分割。 在新季度的第一天,所有前三個月的磁碟分割都會合併為季度磁碟分割。 在新年的第一天,所有前四個季度的磁碟分割都會合併為年磁碟分割。

模型始終保留整個歷史儲存週期的磁碟分割以及目前重新整理週期之前的整個週期磁碟分割。 在範例中,2018年、2019年、2020 年的磁碟分割中保留整整三年的歷史資料,同時也保留 2021Q101 月期間的磁碟分割、2021Q10201 日期間的磁碟分割以及當天重新整理期間的分區。 由於此範例保留三的歷史資料,因此 2018 年磁碟分割會保留到 2022 年 1 月 1 日第一次重新整理。

利用 Power BI 累加式重新整理和即時資料,該服務可以根據原則為您處理磁碟分割管理。 雖然該服務可以為您處理所有磁碟分割管理,但是透過 XMLA 端點使用工具,您可以選擇性地單獨、循序或並行重新整理磁碟分割。

使用 SQL Server Management Studio 的重新整理管理

SQL Server Management Studio (SSMS) 可用於檢視和管理應用程式的累加式重新整理原則所建立的磁碟分割。 例如,藉由使用 SSMS,您重新整理不在累加式重新整理期間中的特定歷史磁碟分割,以執行回溯日期更新,而不需要重新整理所有歷程記錄資料。 SSMS 也可以在啟重時使用,透過批次累加新增/重新整理歷史磁碟分割來載入大型模型的歷史資料。

螢幕擷取畫面顯示 SSMS 中的磁碟分割視窗。

覆寫累加式重新整理行為

利用 SSMS,您還可以藉由使用表格式模型指令碼語言表格式物件模型以更充分地控制如何叫用重新整理。 例如,在 SSMS 的「物件總管」中,以滑鼠右鍵按一下資料表,然後選取 [處理資料表] 功能表選項,然後選取 [指令碼] 按鈕產生 TMSL 重新整理命令。

螢幕擷取畫面顯示 [處理資料表] 對話方塊中的 [指令碼] 按鈕。

這些參數可以與 TMSL 重新整理命令一起使用,以覆寫預設的累加式重新整理行為:

  • applyRefreshPolicy。 如果資料表已定義累加式重新整理原則,applyRefreshPolicy 會判斷是否已套用此原則。 如果未套用此原則,則處理完整作業會將資料分割定義保留不變,而且會完整重新整理資料表中的所有資料分割。 預設值為 True。

  • effectiveDate。 如果套用累加式重新整理原則,其必須知道目前的日期,以判斷累加式重新整理和歷史期間的滾動時段範圍。 effectiveDate 參數可讓您覆寫目前的日期。 這參數適用於測試、示範和商務案例,其中資料會以累加方式重新整理至過去或未來的日期 (例如,未來的預算)。 預設值是目前日期。

{ 
  "refresh": {
    "type": "full",

    "applyRefreshPolicy": true,
    "effectiveDate": "12/31/2013",

    "objects": [
      {
        "database": "IR_AdventureWorks", 
        "table": "FactInternetSales" 
      }
    ]
  }
}

若要深入了解如何使用 TMSL 覆寫預設的累加式重新整理行為,請參閱 Refresh 命令 \(部分機器翻譯\)。

確保最佳效能

對於每個重新整理作業,Power BI 服務可能會對每個累加式重新整理磁碟分割的資料來源傳送初始化查詢。 您可以藉由確保以下設定減少初始化查詢的數量來提高累加式重新整理效能:

  • 您為其設定累加式重新整理的表格應從單一資料來源取得資料。 如果表格從多個資料來源取得資料,則服務針對每個重新整理作業所傳送的查詢數量乘以資料來源數量,可能會降低重新整理效能。 確保累加式重新整理表格的查詢針對單一資料來源。
  • 對於同時具有匯入磁碟分割的累加式重新整理和直接查詢即時資料的解決方案,所有磁碟分割必須從單一資料來源查詢資料。
  • 如果您的安全性需求允許,請將資料來源隱私權等級設定設為組織公用。 預設情況下,隱私權等級為私人,但此等級可能會防止與其他雲端來源交換資料。 若要設定隱私權等級,請選取 [更多選項] 功能表,然後選擇 [設定]>[資料來源認證]>[編輯認證]>[此資料來源的隱私權等級設定]。 如果在發佈到服務之前在 Power BI Desktop 模型中設定隱私權等級,則在發佈時不會將其傳輸到服務。 您仍然必須在服務的語義模型設定中加以設定。 若要深入了解,請參閱隱私權等級
  • 如果使用內部部署的資料閘道,請確保您使用的是版本 3000.77.3 或更高版本。

防止初始完整重新整理逾時

發佈到 Power BI 服務之後,模型的初始完整重新整理作業會為累加式重新整理表格建立磁碟分割,載入並處理累加式重新整理原則中定義的整個期間的歷史資料。 對於某些載入和處理大量資料的模型,初始重新整理作業所花費的時間可能會超過服務強制實施的重新整理時間限制或資料來源強制實施的查詢時間限制。

啟動初始重新整理作業允許服務為累加式重新整理表格建立磁碟分割物件,但不會將歷史資料載入和處理到任何磁碟分割。 然後使用 SSMS 選擇性地處理磁碟分割。 根據每個磁碟分割要載入的資料量,您可以循序或小批次處理每個磁碟分割,以減少其中一或多個磁碟分割導致逾時的可能性。 以下方法適用於任何資料來源。

套用重新整理原則

開放原始碼的 Tabular Editor 2 工具提供一種啟動初始重新整理作業的簡單方式。 將具有為其定義的累加式重新整理原則的模型從 Power BI Desktop 發佈到服務之後,在讀取/寫入模式下使用 XMLA 端點連線到該模型。 對累加式重新整理表格執行 [套用重新整理原則]。 僅套用原則時,會建立磁碟分割,但不會將資料載入到其中。 然後連線 SSMS,循序或批次重新整理磁碟分割,載入並處理資料。 如需詳細資訊,請參閱表格編輯器文件中的累加式重新整理

螢幕擷取畫面顯示已選取「套用重新整理原則」的表格編輯器。

針對空白磁碟分割的 Power Query 篩選器

在將模型發佈到服務之前,在 Power Query 編輯器中,對 ProductKey 欄新增另一個篩選器,以篩選掉除了 0 以外的任何值,或有效地篩選掉 FactInternetSales 表格中的所有資料。

螢幕擷取畫面顯示 Power Query 編輯器,其中包含篩選掉產品金鑰的程式碼。

在 Power Query 編輯器中選取 [關閉並套用]、定義累加式重新整理原則並且儲存模型之後,模型就會發佈到服務。 從服務中,對模型執行初始重新整理作業。 FactInternetSales 表格的磁碟分割是根據原則而建立,但不會載入和處理任何資料,因為會篩選掉所有資料。

初始重新整理作業完成之後,返回 Power Query 編輯器,就會移除 ProductKey 欄上的另一個篩選器。 在 Power Query 編輯器中選取 [關閉並套用] 並儲存模型之後,此模型不會再發佈。 如果再次發佈模型,其將覆寫累加式重新整理原則設定,並在從服務執行後續累加式重新整理作業時強制對模型進行完整重新整理。 相反的,您可以使用應用程式生命週期管理 (ALM) 工具組執行 [僅限中繼資料部署],該工具組會從模型中移除 ProductKey 欄上的篩選器。 然後可以使用 SSMS 選擇性地處理磁碟分割。 當所有磁碟分割都已完全處理時 (必須包含從 SSMS 對所有磁碟分割進行流程重新計算),來自服務的模型上的後續重新整理作業將僅重新整理累加式重新整理磁碟分割。

提示

請務必查看 Power BI 的 BI 專家社群提供的影片、部落格及更多內容。

若要深入了解從 SSMS 處理表格和磁碟分割,請參閱處理資料庫、表格或磁碟分割 (Analysis Services)。 若要深入了解使用 TMSL 處理模型、表格和或磁碟分割,請參閱重新整理命令 (TMSL)

偵測資料變更的自訂查詢

可以使用 TMSL 和/或 TOM 來覆寫偵測到的資料變更行為。 此方法不僅可以用來避免保存記憶體內部快取中的最後更新資料行,也可以啟用藉由擷取、轉換和載入 ETL 程序備妥設定/或指令資料表的案例,以只標記需要重新整理的資料分割。 此方法可以建立更有效率的累加式重新整理程序,不論是多久前進行過資料更新,都只會重新整理所需的期間。

pollingExpression 的目標是輕量 M 運算式或另一個 M 查詢的名稱。 其必須傳回純量值,而且會針對每個資料分割執行。 如果傳回的值與上次累加式重新整理的值不同,則會將資料分割標示為完整處理。

下列範例涵蓋回溯日期變更的歷史期間中所有 120 個月。 指定 120 個月而不是 10 年,表示資料壓縮可能不會相當有效率,但是可避免必須重新整理整個歷程記錄年份,當一個月份就足以進行回溯日期變更時,這樣會更耗費資源。

"refreshPolicy": {
    "policyType": "basic",
    "rollingWindowGranularity": "month",
    "rollingWindowPeriods": 120,
    "incrementalGranularity": "month",
    "incrementalPeriods": 120,
    "pollingExpression": "<M expression or name of custom polling query>",
    "sourceExpression": [
    "let ..."
    ]
}

提示

請務必查看 Power BI 的 BI 專家社群提供的影片、部落格及更多內容。

僅限中繼資料部署

從 Power BI Desktop 將新版本 .pbix 檔案發佈至工作區時,如果已存在相同名稱的模型,系統會提示您取代現有的模型。

螢幕擷取畫面顯示 [取代模型] 對話方塊。

在某些情況下,您可能不想要取代模型,特別是累加式重新整理。 Power BI Desktop 中的模型可能會比 Power BI 服務中的模型小很多。 如果 Power BI 服務中的模型已套用累加式重新整理原則,則在模型被取代時,可能會遺失數年的歷程記錄資料。 重新整理所有歷程記錄資料可能需要數小時的時間,並且導致使用者的系統停機時間。

相反的,最好執行僅中繼資料部署,這樣可以部署新物件而不會遺失歷史資料。 例如,如果您已新增幾個量值,則可以只部署新的量值,而不需要重新整理資料,節省時間。

對於指派至設定為 XMLA 端點讀取/寫入的 Premium 容量工作區,相容工具支援僅中繼資料部署。 例如,ALM 工具組是用於 Power BI 模型的結構描述 diff 工具,而且只能用來執行中繼資料的部署。

Analysis Services Git 存放庫 (英文) 下載並安裝最新版本的 ALM 工具組。 Microsoft 文件中不包含使用 ALM 工具組的逐步指導。 在 [說明] 功能區中提供 ALM 工具組文件連結和可支援性的資訊。 若要執行僅限中繼資料部署,請執行比較並選取執行中 Power BI Desktop 執行個體作為來源,以及選取 Power BI 服務中的現有模型作為目標。 請考量顯示的差異,並略過具有累加式重新整理資料分割的資料表更新,或使用 [選項] 對話方塊來保留資料表更新的資料分割。 驗證選取範圍,以確保目標模型的完整性,然後更新。

螢幕擷取畫面顯示 ALM 工具組視窗。

以程式設計方式新增累加式重新整理原則和即時資料

您也可以使用 TMSL 和 TOM 透過 XMLA 端點將累加式重新整理原則新增至現有模型。

注意

若為避免相容性問題,請確保使用最新版本的 Analysis Services 用戶端程式庫。 例如,若要使用混合式原則,版本必須為 19.27.1.8 或更高版本。

此程序包括以下步驟:

  1. 確保目標模型具有所需的最低相容性等級。 在 SSMS 中,以滑鼠右鍵按一下 [模型名稱]>[屬性]>[相容性等級]。 若要提高相容性等級,請使用 createOrReplace TMSL 指令碼或查看以下 TOM 範例程式碼作為範例。

    a. Import policy - 1550
    b. Hybrid policy - 1565
    
  2. RangeStartRangeEnd 參數新增至模型運算式。 如有必要,也可以新增函數將日期/時間值轉換為日期索引鍵。

  3. 定義具有所需封存 (滾動視窗) 和累加式重新整理週期的 RefreshPolicy 物件,以及根據 RangeStartRangeEnd 參數篩選目標表格的來源運算式。 根據您的即時資料需求,將重新整理原則模式設定為 [匯入] 或 [混合式]。 混合式會導致 Power BI 將 DirectQuery 磁碟分割新增至表格中,以從上次重新整理時間之後發生的資料來源中取得最新的變更。

  4. 將重新整理原則新增至表格並執行完整重新整理,以便 Power BI 根據您的需求對資料表進行磁碟分割。

以下程式碼範例示範如何使用 TOM 執行前面的步驟。 如果您想依現狀使用此範例,則必須擁有 AdventureWorksDW 資料庫的複本並將 FactInternetSales 表格匯入到模型中。 此程式碼範例假設模型中不存在 RangeStartRangeEnd 參數以及 DateKey 函數。 只需匯入 FactInternetSales 表格並將模型發佈到 Power BI Premium 上的工作區即可。 然後更新 workspaceUrl,以便程式碼範例可以連線到您的模型。 根據需要更新任何更多的程式碼行。

using System;
using TOM = Microsoft.AnalysisServices.Tabular;
namespace Hybrid_Tables
{
    class Program
    {
        static string workspaceUrl = "<Enter your Workspace URL here>";
        static string databaseName = "AdventureWorks";
        static string tableName = "FactInternetSales";
        static void Main(string[] args)
        {
            using (var server = new TOM.Server())
            {
                // Connect to the dataset.
                server.Connect(workspaceUrl);
                TOM.Database database = server.Databases.FindByName(databaseName);
                if (database == null)
                {
                    throw new ApplicationException("Database cannot be found!");
                }
                if(database.CompatibilityLevel < 1565)
                {
                    database.CompatibilityLevel = 1565;
                    database.Update();
                }
                TOM.Model model = database.Model;
                // Add RangeStart, RangeEnd, and DateKey function.
                model.Expressions.Add(new TOM.NamedExpression {
                    Name = "RangeStart",
                    Kind = TOM.ExpressionKind.M,
                    Expression = "#datetime(2021, 12, 30, 0, 0, 0) meta [IsParameterQuery=true, Type=\"DateTime\", IsParameterQueryRequired=true]"
                });
                model.Expressions.Add(new TOM.NamedExpression
                {
                    Name = "RangeEnd",
                    Kind = TOM.ExpressionKind.M,
                    Expression = "#datetime(2021, 12, 31, 0, 0, 0) meta [IsParameterQuery=true, Type=\"DateTime\", IsParameterQueryRequired=true]"
                });
                model.Expressions.Add(new TOM.NamedExpression
                {
                    Name = "DateKey",
                    Kind = TOM.ExpressionKind.M,
                    Expression =
                        "let\n" +
                        "    Source = (x as datetime) => Date.Year(x)*10000 + Date.Month(x)*100 + Date.Day(x)\n" +
                        "in\n" +
                        "    Source"
                });
                // Apply a RefreshPolicy with Real-Time to the target table.
                TOM.Table salesTable = model.Tables[tableName];
                TOM.RefreshPolicy hybridPolicy = new TOM.BasicRefreshPolicy
                {
                    Mode = TOM.RefreshPolicyMode.Hybrid,
                    IncrementalPeriodsOffset = -1,
                    RollingWindowPeriods = 1,
                    RollingWindowGranularity = TOM.RefreshGranularityType.Year,
                    IncrementalPeriods = 1,
                    IncrementalGranularity = TOM.RefreshGranularityType.Day,
                    SourceExpression =
                        "let\n" +
                        "    Source = Sql.Database(\"demopm.database.windows.net\", \"AdventureWorksDW\"),\n" +
                        "    dbo_FactInternetSales = Source{[Schema=\"dbo\",Item=\"FactInternetSales\"]}[Data],\n" +
                        "    #\"Filtered Rows\" = Table.SelectRows(dbo_FactInternetSales, each [OrderDateKey] >= DateKey(RangeStart) and [OrderDateKey] < DateKey(RangeEnd))\n" +
                        "in\n" +
                        "    #\"Filtered Rows\""
                };
                salesTable.RefreshPolicy = hybridPolicy;
                model.RequestRefresh(TOM.RefreshType.Full);
                model.SaveChanges();
            }
            Console.WriteLine("{0}{1}", Environment.NewLine, "Press [Enter] to exit...");
            Console.ReadLine();
        }
    }
}