JavaScriptを有効にしてください

Azure Monitor のテーブルプランの違いを試し隊

 ·   7 分で読めます  ·   [Kento GitHub Copilot]

本記事は GitHub Copilot を活用して作成しています。

Azure Monitor の Log Analytics には、データの保存とクエリの方法を制御するための3つのテーブルプランがあります。それぞれのプランには異なる特性があり、用途に応じて使い分けることが重要です。

本記事では、これらのプランの違いを実際に検証し、特に検索クエリのパフォーマンスに焦点を当てて比較します。

テーブルプランとは

Azure Monitor Log Analytics には以下の3つのテーブルプランがあります:

プラン 英語名 特徴
分析プラン Analytics Plan 検索クエリが無料、フル機能のクエリ
基本プラン Basic Plan 取り込みコスト削減、単一テーブルのクエリ
補助プラン Auxiliary Plan 取り込みコスト大幅削減、単一テーブルのクエリ、検索クエリのパフォーマンスは制限される

詳細は Azure Monitor ログのデータ プラットフォーム - テーブル プラン を参照してください。

検証の概要

今回の検証では、まったく同じカスタムテキストログを3つのプランのそれぞれで採取し、同一のクエリを実行してパフォーマンスを比較します。

検証環境

architecture-beta
    group rg(azure:resource-groups)[Resource Group]
    
    service la(azure:log-analytics-workspaces)[Log Analytics Workspace] in rg
    service dcr(azure:data-collection-rules)[Data Collection Rules] in rg
    service vm(azure:virtual-machine)[Virtual Machine] in rg    
    
  vm:R --> L:dcr
  dcr:R --> L:la
  • Log Analytics ワークスペース: 1つ
    • カスタムテーブル: 3つ(各プラン用)
      • customtext_analysis_CL (分析プラン)
      • customtext_basic_CL (基本プラン)
      • customtext_auxiliary_CL (補助プラン)
  • データ収集ルール: 1つ
  • Windows 仮想マシン: 1台

※記載を省略していますが、Vnet や NSG などのネットワーク関連リソースおよび自動展開で利用するリソースも作成しています。

検証パターン

以下の3つのパターンでクエリパフォーマンスを検証します:

  1. パターン1: 過去1時間分を検索
  2. パターン2: RawData の内容を展開

ざっくり手順

  1. Bicep ファイルの準備
  2. Bicep デプロイの実行(環境全体の作成)
  3. パターン1: 検索パフォーマンス検証
  4. パターン2: RawData の内容を展開

1. Bicep ファイルの準備

検証環境全体を Bicep で作成します。
使用した Bicep ファイルは以下の GitHub リポジトリで公開しています:
https://github.com/NakayamaKento/Azure_Bicep/tree/main/Blog/log_analytics_table_plan

graph TB
    subgraph "Azure リソースグループ"
        subgraph "ネットワーク"
            VNet["Virtual Network<br/>10.0.0.0/16"]
            NSG["Network Security Group"]
            VNet -->|関連付け| NSG
        end
        
        subgraph "コンピュート"
            VM["Windows VM<br/>Windows Server 2022<br/>Standard_D4s_v4"]
            PIP["Public IP"]
            VM -->|関連付け| PIP
            VM -->|配置| VNet
        end
        
        subgraph "VM 拡張機能"
            AMA["Azure Monitor Agent<br/>(Monitoring Agent)"]
            CSE["Custom Script Extension"]
            VM -->|インストール| AMA
            VM -->|インストール| CSE
        end
        
        subgraph "スクリプト実行"
            CSE -->|ダウンロード & 配置| Scripts["C:\\Scripts\\<br/>- customlog.ps1<br/>- register-imds-startup.ps1"]
            Scripts -->|起動時タスク登録| Task["Windows スケジュールタスク<br/>(起動時実行)"]
            Task -->|定期実行| LogGen["カスタムログ生成<br/>C:\\Logs\\imds-customtext.log"]
        end
        
        subgraph "Log Analytics"
            LAW["Log Analytics Workspace"]
            Table1["customtext_auxiliary_CL<br/>(Auxiliary Plan)"]
            Table2["customtext_basic_CL<br/>(Basic Plan)"]
            Table3["customtext_analysis_CL<br/>(Analytics Plan)"]
            LAW -->|含む| Table1
            LAW -->|含む| Table2
            LAW -->|含む| Table3
        end
        
        subgraph "データ収集"
            DCR["Data Collection Rule"]
            AMA -->|データ収集| LogGen
            AMA -->|送信| DCR
            DCR -->|ルーティング| Table1
            DCR -->|ルーティング| Table2
            DCR -->|ルーティング| Table3
        end
        
        subgraph "デプロイメント自動化"
            ManagedID["Managed Identity"]
            DeployScript["Deployment Script<br/>(カスタムテーブル作成)"]
            RestartScript["Deployment Script<br/>(VM 再起動)"]
            SA["Storage Account<br/>(スクリプト用)"]
            
            DeployScript -->|使用| ManagedID
            DeployScript -->|REST API 呼び出し| LAW
            DeployScript -->|利用| SA
            RestartScript -->|VM 再起動| VM
            RestartScript -->|利用| SA
            RestartScript -->|使用| ManagedID
        end
    end
    
    GitHub["GitHub Repository<br/>(スクリプト配信)"] -.->|ダウンロード| CSE
    
    classDef network fill:#e1f5ff,stroke:#0078d4,stroke-width:2px
    classDef compute fill:#fff4e1,stroke:#ff8c00,stroke-width:2px
    classDef monitoring fill:#e8f5e9,stroke:#4caf50,stroke-width:2px
    classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:2px
    classDef script fill:#fff3e0,stroke:#ff9800,stroke-width:2px
    
    class VNet,NSG,PIP network
    class VM,AMA,CSE compute
    class LAW,Table1,Table2,Table3,DCR monitoring
    class SA,LogGen storage
    class ManagedID,DeployScript,RestartScript,Scripts,Task,GitHub script

補足:カスタムテーブル作成用 PowerShell スクリプトの準備

補助プランのテーブルは Azure Portal から作成できず、API を使用する必要があります。
今回はまとめて 3つのプラン(分析、基本、補助)のテーブルをまとめて作成します。
上述のリポジトリでも公開していますが、抜粋して以下に示します。

deploymentScript の実行内容
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
$WorkspaceName     = $env:WorkspaceName
$ResourceGroupName = $env:ResourceGroupName
$SubscriptionId    = $env:SubscriptionId
# Connect using Managed Identity
Connect-AzAccount -Identity

$ApiVersion = "2023-01-01-preview"
$BasePath   = "/subscriptions/$SubscriptionId/resourcegroups/$ResourceGroupName/providers/microsoft.operationalinsights/workspaces/$WorkspaceName"


# Create Auxiliary Table customtext_analysis_CL in Log Analytics Workspace
$tableParams = @'
{
    "properties": {
        "schema": {
               "name": "customtext_auxiliary_CL",
               "columns": [
                    {
                        "name": "TimeGenerated",
                        "type": "DateTime"
                    },
                    {
                        "name": "RawData",
                        "type": "string"
                    }
              ]
        },
        "plan": "Auxiliary"
    }
}
'@

Invoke-AzRestMethod -Path "$BasePath/tables/customtext_auxiliary_CL?api-version=$ApiVersion" -Method PUT -payload $tableParams

# Create Basic Table customtext_basic_CL in Log Analytics Workspace
$tableParams = @'
{
    "properties": {
        "schema": {
               "name": "customtext_basic_CL",
               "columns": [
                    {
                        "name": "TimeGenerated",
                        "type": "DateTime"
                    },
                    {
                        "name": "RawData",
                        "type": "string"
                    }
              ]
        },
        "plan": "Basic"
    }
}
'@

Invoke-AzRestMethod -Path "$BasePath/tables/customtext_basic_CL?api-version=$ApiVersion" -Method PUT -payload $tableParams      

# Create Analytics Table customtext_analysis_CL in Log Analytics Workspace
$tableParams = @'
{
    "properties": {
        "schema": {
               "name": "customtext_analysis_CL",
               "columns": [
                    {
                        "name": "TimeGenerated",
                        "type": "DateTime"
                    },
                    {
                        "name": "RawData",
                        "type": "string"
                    }
              ]
        },
        "plan": "Analytics"
    }
}
'@

Invoke-AzRestMethod -Path "$BasePath/tables/customtext_analysis_CL?api-version=$ApiVersion" -Method PUT -payload $tableParams    
以前までカスタム ログを収集する場合は、データ収集エンドポイントを作成する必要がありました。
現在では Log Analytics ワークスペースに直接データを送信できるため、エンドポイントの作成は不要です。
Azure Monitor のデータ収集エンドポイント - Azure Monitor | Microsoft Learn

2. Bicep デプロイの実行(環境全体の作成)

Bicep ファイルをデプロイして、検証環境全体を作成します。
カスタムログを収集する設定もカスタム スクリプト拡張機能を使って Bicep 内で行っています。

image01
作成されたリソース:

デプロイ後、Azure Portal から作成されたデータ収集ルールを確認できます。
しかし、Azure Portal 上ではデータ収集ルールのすべての設定内容を確認することができません。

image02
作成されたデータ収集ルール(Portal):

JSON 形式であれば設定内容を確認することができます

image03
作成されたデータ収集ルール(JSON):

3. パターン1: 検索パフォーマンス検証

各プランで過去1時間分のデータを取得するクエリを実行し、実行時間を比較します。

クエリ

// 分析プラン
customtext_analysis_CL
| where TimeGenerated > ago(1h)
// 基本プラン
customtext_basic_CL
| where TimeGenerated > ago(1h)
// 補助プラン
customtext_auxiliary_CL
| where TimeGenerated > ago(1h)

結果

プラン レコード数 実行時間
分析プラン 58 0.453秒
基本プラン 58 1.090秒
補助プラン 58 3.617秒
image04
パターン1の検証結果:

考察:

  • 分析プランが最も高速で、補助プランは分析プランの約8倍の時間がかかりました
  • 基本プランは中間的な性能を示しました
  • データ量が少ない場合でも明確な差が見られます

4. パターン2: RawData の内容を展開

RawData を展開するクエリを実行します。

クエリ

// 分析プラン
customtext_analysis_CL
// 先頭4項目
| extend LogDateTime = extract(@"^([^,]+)",           1, RawData),
         Sequence    = extract(@"^[^,]+,([^,]+)",     1, RawData),
         Level       = extract(@"^[^,]+,[^,]+,([^,]+)", 1, RawData),
         Category    = extract(@"^[^,]+,[^,]+,[^,]+,([^,]+)", 1, RawData)
// key=value 部分
| extend vmName      = extract(@"vmName=([^;]*)",          1, RawData),
         vmSize      = extract(@"vmSize=([^;]*)",          1, RawData),
         location    = extract(@"location=([^;]*)",        1, RawData),
         subscriptionId = extract(@"subscriptionId=([^;]*)", 1, RawData),
         resourceGroup  = extract(@"resourceGroup=([^;]*)", 1, RawData),
         privateIps  = extract(@"privateIps=([^;]*)",      1, RawData),
         publicIps   = extract(@"publicIps=([^;]*)",       1, RawData),
         scheduledEventsCount = toint(extract(@"scheduledEventsCount=([^;]*)", 1, RawData)),
         attestationPresent   = tobool(extract(@"attestationPresent=([^;]*)", 1, RawData)),
         collectionTs         = todatetime(extract(@"collectionTs=([^;]*)", 1, RawData))
// 基本プラン
customtext_basic_CL
// 先頭4項目
| extend LogDateTime = extract(@"^([^,]+)",           1, RawData),
         Sequence    = extract(@"^[^,]+,([^,]+)",     1, RawData),
         Level       = extract(@"^[^,]+,[^,]+,([^,]+)", 1, RawData),
         Category    = extract(@"^[^,]+,[^,]+,[^,]+,([^,]+)", 1, RawData)
// key=value 部分
| extend vmName      = extract(@"vmName=([^;]*)",          1, RawData),
         vmSize      = extract(@"vmSize=([^;]*)",          1, RawData),
         location    = extract(@"location=([^;]*)",        1, RawData),
         subscriptionId = extract(@"subscriptionId=([^;]*)", 1, RawData),
         resourceGroup  = extract(@"resourceGroup=([^;]*)", 1, RawData),
         privateIps  = extract(@"privateIps=([^;]*)",      1, RawData),
         publicIps   = extract(@"publicIps=([^;]*)",       1, RawData),
         scheduledEventsCount = toint(extract(@"scheduledEventsCount=([^;]*)", 1, RawData)),
         attestationPresent   = tobool(extract(@"attestationPresent=([^;]*)", 1, RawData)),
         collectionTs         = todatetime(extract(@"collectionTs=([^;]*)", 1, RawData))
// 補助プラン
customtext_auxiliary_CL
// 先頭4項目
| extend LogDateTime = extract(@"^([^,]+)",           1, RawData),
         Sequence    = extract(@"^[^,]+,([^,]+)",     1, RawData),
         Level       = extract(@"^[^,]+,[^,]+,([^,]+)", 1, RawData),
         Category    = extract(@"^[^,]+,[^,]+,[^,]+,([^,]+)", 1, RawData)
// key=value 部分
| extend vmName      = extract(@"vmName=([^;]*)",          1, RawData),
         vmSize      = extract(@"vmSize=([^;]*)",          1, RawData),
         location    = extract(@"location=([^;]*)",        1, RawData),
         subscriptionId = extract(@"subscriptionId=([^;]*)", 1, RawData),
         resourceGroup  = extract(@"resourceGroup=([^;]*)", 1, RawData),
         privateIps  = extract(@"privateIps=([^;]*)",      1, RawData),
         publicIps   = extract(@"publicIps=([^;]*)",       1, RawData),
         scheduledEventsCount = toint(extract(@"scheduledEventsCount=([^;]*)", 1, RawData)),
         attestationPresent   = tobool(extract(@"attestationPresent=([^;]*)", 1, RawData)),
         collectionTs         = todatetime(extract(@"collectionTs=([^;]*)", 1, RawData))

結果

プラン レコード数 実行時間
分析プラン 58 1.085秒
基本プラン 58 1.016秒
補助プラン 58 1.493秒
image05
パターン2の検証結果:

考察:

  • パターン1と比較して、そこまで大きな変化は見られません
  • 補助プランのパフォーマンスは改善したように見えますが、何度か実行するとムラがあり、パフォーマンスは安定しない印象です

まとめ

Azure Monitor Log Analytics の3つのテーブルプラン(分析、基本、補助)について、実際のカスタムログを使用して検索パフォーマンスを検証しました。

補助プランはクエリが最適化されていない。とドキュメントに記載がありましたが実行した感覚としてはパフォーマンスにムラがありました。
早い時もあれば、遅い時もあるということで確かに最適化はされていなさそうです。

参考

共有

Kento
著者
[Kento GitHub Copilot]
2020年に新卒で IT 企業に入社. インフラエンジニア(主にクラウド)として活動中