次の方法で共有


Kusto 照会言語 (KQL) グラフ セマンティクスのベスト プラクティス

この記事では、さまざまなユース ケースやシナリオで KQL のグラフ セマンティクス機能を効果的かつ効率的に使用する方法について説明します。 構文と演算子を使用してグラフを作成およびクエリする方法と、それらを他の KQL の機能と関数と統合する方法を示します。 また、メモリやパフォーマンスの制限を超えるグラフの作成、不適切または互換性のないフィルター、プロジェクション、集計の適用など、ユーザーが一般的な落とし穴やエラーを回避するのにも役立ちます。

グラフのサイズ

グラフ作成演算子、グラフのメモリ内表現を作成します。 グラフ構造自体とそのプロパティで構成されます。 グラフを作成するときは、適切なフィルター、プロジェクション、集計を使用して、関連するノードとエッジとそのプロパティのみを選択します。

次の例は、ノードとエッジの数とそのプロパティを減らす方法を示しています。 このシナリオでは、Bob がマネージャーを Alice から Eve に変更し、ユーザーは組織のグラフの最新の状態のみを表示したいと考えています。 グラフのサイズを小さくするために、ノードは最初に組織のプロパティによってフィルター処理され、次に project-away 演算子を使用してプロパティがグラフから削除されます。 エッジでも同じことが起こります。 次に、グラフの最後の既知の状態を取得するためにarg_max共に演算子を集計します。

let allEmployees = datatable(organization: string, name:string, age:long)
[
  "R&D", "Alice", 32,
  "R&D","Bob", 31,
  "R&D","Eve", 27,
  "R&D","Mallory", 29,
  "Marketing", "Alex", 35
];
let allReports = datatable(employee:string, manager:string, modificationDate: datetime)
[
  "Bob", "Alice", datetime(2022-05-23),
  "Bob", "Eve", datetime(2023-01-01),
  "Eve", "Mallory", datetime(2022-05-23),
  "Alice", "Dave", datetime(2022-05-23)
];
let filteredEmployees =
    allEmployees
    | where organization == "R&D"
    | project-away age, organization;
let filteredReports =
    allReports
    | summarize arg_max(modificationDate, *) by employee
    | project-away modificationDate;
filteredReports
| make-graph employee --> manager with filteredEmployees on name
| graph-match (employee)-[hasManager*2..5]-(manager)
  where employee.name == "Bob"
  project employee = employee.name, topManager = manager.name

出力

employee topManager
Bob Mallory

グラフの最後の既知の状態

グラフのサイズの例では、演算子と集計関数を使用してsummarize、グラフのエッジの最後の既知の状態を取得する方法をarg_max示しました。 最後の既知の状態の取得は、コンピューティング集中型の操作です。

次のように、クエリのパフォーマンスを向上させるために具体化されたビューを作成することを検討してください。

  1. モデルの一部としてバージョンの概念を持つテーブルを作成します。 後でグラフ時系列を datetime 作成するために使用できる列を使用することをお勧めします。

    .create table employees (organization: string, name:string, stateOfEmployment:string, properties:dynamic, modificationDate:datetime)
    
    .create table reportsTo (employee:string, manager:string, modificationDate: datetime)
    
  2. テーブルごとに具体化されたビューを作成し、arg_max集計関数を使用して、従業員の最後の既知の状態と reportsTo リレーションシップを決定します。

    .create materialized-view employees_MV on table employees
    {
        employees
        | summarize arg_max(modificationDate, *) by name
    }
    
    .create materialized-view reportsTo_MV on table reportsTo
    {
        reportsTo
        | summarize arg_max(modificationDate, *) by employee
    }
    
  3. 具体化されたビューの具体化されたコンポーネントのみが使用され、追加のフィルターとプロジェクションが適用されるようにする 2 つの関数を作成します。

    .create function currentEmployees () {
        materialized_view('employees_MV')
        | where stateOfEmployment == "employed"
    }
    
    .create function reportsTo_lastKnownState () {
        materialized_view('reportsTo_MV')
        | project-away modificationDate
    }
    

具体化されたクエリを使用すると、大規模なグラフに対するクエリの高速化と効率が向上します。 また、グラフの最新の状態に対するコンカレンシーが高くなり、待機時間が短いクエリも可能になります。 必要に応じて、従業員と reportsTo テーブルに基づいてグラフ履歴のクエリを実行できます

let filteredEmployees =
    currentEmployees
    | where organization == "R&D"
    | project-away organization;
reportsTo_lastKnownState
| make-graph employee --> manager with filteredEmployees on name
| graph-match (employee)-[hasManager*2..5]-(manager)
  where employee.name == "Bob"
  project employee = employee.name, reportingPath = hasManager.manager

グラフの時間移動

一部のシナリオでは、特定の時点でのグラフの状態に基づいてデータを分析する必要があります。 グラフの時間移動では、arg_max集計関数を使用して、時間フィルターと集計の組み合わせを使用します。

次の KQL ステートメントは、グラフの興味深い時点を定義するパラメーターを持つ関数を作成します。 既製のグラフを返します。

.create function graph_time_travel (interestingPointInTime:datetime ) {
    let filteredEmployees =
        employees
        | where modificationDate < interestingPointInTime
        | summarize arg_max(modificationDate, *) by name;
    let filteredReports =
        reportsTo
        | where modificationDate < interestingPointInTime
        | summarize arg_max(modificationDate, *) by employee
        | project-away modificationDate;
    filteredReports
    | make-graph employee --> manager with filteredEmployees on name
}

この関数を設定すると、ユーザーはクエリを作成して、2022 年 6 月のグラフに基づいて Bob のトップ マネージャーを取得できます。

graph_time_travel(datetime(2022-06-01))
| graph-match (employee)-[hasManager*2..5]-(manager)
  where employee.name == "Bob"
  project employee = employee.name, reportingPath = hasManager.manager

出力

employee topManager
Bob Dave

複数のノードとエッジの種類の処理

複数のノードの種類で構成されるグラフを使用して時系列データをコンテキスト化することが必要な場合があります。 このシナリオを処理する 1 つの方法は、正規モデルで表される汎用プロパティ グラフを作成することです。

場合によっては、複数のノードタイプを持つグラフを使用して時系列データをコンテキスト化することが必要になる場合があります。 次のような正規モデルに基づく汎用プロパティ グラフを作成することで、問題にアプローチできます。

  • ノード
    • nodeId (string)
    • label (string)
    • properties (dynamic)
  • エッジ
    • source (string)
    • destination (string)
    • label (string)
    • properties (dynamic)

次の例は、データを正規モデルに変換する方法とクエリを実行する方法を示しています。 グラフのノードとエッジのベース テーブルには、スキーマが異なります。

このシナリオには、設備が正常に動作しない理由と、その修正を担当する工場マネージャーが含まれます。 マネージャーは、生産現場の資産グラフと、毎日変更されるメインテナント スタッフ階層を組み合わせたグラフを使用することにしました。

次のグラフは、資産とその時系列 (速度、温度、圧力など) の関係を示しています。 オペレーターと資産 (ポンプなど) は、操作エッジを介して接続されます。 オペレーター自体は、管理に関するレポートを作成します。

プロパティ グラフのシナリオに関するインフォグラフィック。

これらのエンティティのデータは、クラスターに直接格納することも、Azure Cosmos DB、Azure SQL、Azure Digital Twin などの別のサービスへのクエリ フェデレーションを使用して取得することもできます。 この例を示すために、次の表形式データがクエリの一部として作成されます。

let sensors = datatable(sensorId:string, tagName:string, unitOfMeasuree:string)
[
  "1", "temperature", "°C",
  "2", "pressure", "Pa",
  "3", "speed", "m/s"
];
let timeseriesData = datatable(sensorId:string, timestamp:string, value:double, anomaly: bool )
[
    "1", datetime(2023-01-23 10:00:00), 32, false,
    "1", datetime(2023-01-24 10:00:00), 400, true,
    "3", datetime(2023-01-24 09:00:00), 9, false
];
let employees = datatable(name:string, age:long)
[
  "Alice", 32,
  "Bob", 31,
  "Eve", 27,
  "Mallory", 29,
  "Alex", 35,
  "Dave", 45
];
let allReports = datatable(employee:string, manager:string)
[
  "Bob", "Alice",
  "Alice", "Dave",
  "Eve", "Mallory",
  "Alex", "Dave"
];
let operates = datatable(employee:string, machine:string, timestamp:datetime)
[
  "Bob", "Pump", datetime(2023-01-23),
  "Eve", "Pump", datetime(2023-01-24),
  "Mallory", "Press", datetime(2023-01-24),
  "Alex", "Conveyor belt", datetime(2023-01-24),
];
let assetHierarchy = datatable(source:string, destination:string)
[
  "1", "Pump",
  "2", "Pump",
  "Pump", "Press",
  "3", "Conveyor belt"
];

従業員、センサーおよびその他のエンティティとリレーションシップは、正規のデータ モデルを共有しません。 共用体演算子使用して、データの結合と正規化を行うことができます。

次のクエリでは、センサー データを時系列データと結合して、異常な読み取り値を持つセンサーを見つけます。 次に、プロジェクションを使用してグラフ ノードの共通モデルを作成します。

let nodes =
    union
        (
            sensors
            | join kind=leftouter
            (
                timeseriesData
                | summarize hasAnomaly=max(anomaly) by sensorId
            ) on sensorId
            | project nodeId = sensorId, label = "tag", properties = pack_all(true)
        ),
        ( employees | project nodeId = name, label = "employee", properties = pack_all(true));

エッジも同様の方法で変換されます。

let edges =
    union
        ( assetHierarchy | extend label = "hasParent" ),
        ( allReports | project source = employee, destination = manager, label = "reportsTo" ),
        ( operates | project source = employee, destination = machine, properties = pack_all(true), label = "operates" );

正規化されたノードとエッジ データを使用すると、次のように make-graph 演算子使用してグラフを作成できます。

let graph = edges
| make-graph source --> destination with nodes on nodeId;

作成したら、パス パターンを定義し、必要な情報を投影します。 パターンは、タグ ノードから始まり、その後にアセットの可変長エッジが続きます。 この資産は、reportsTo と呼ばれる可変長エッジを介してトップ マネージャーに報告するオペレーターによって運用されます。 グラフ一致演算子制約セクション。この例では、異常があり、特定の日に操作されたタグにタグが減ります。

graph
| graph-match (tag)-[hasParent*1..5]->(asset)<-[operates]-(operator)-[reportsTo*1..5]->(topManager)
    where tag.label=="tag" and tobool(tag.properties.hasAnomaly) and
        startofday(todatetime(operates.properties.timestamp)) == datetime(2023-01-24)
        and topManager.label=="employee"
    project
        tagWithAnomaly = tostring(tag.properties.tagName),
        impactedAsset = asset.nodeId,
        operatorName = operator.nodeId,
        responsibleManager = tostring(topManager.nodeId)

出力

tagWithAnomaly impactedAsset operatorName responsibleManager
温度 ポンプ Eve Mallory

グラフ 一致のプロジェクションは、温度センサーが指定した日に異常を示した情報を出力します。 最終的にマローリーに報告するイブによって運営されました。 この情報を使用すると、工場のマネージャーは Eve と Mallory に連絡して、異常をより深く理解できます。