다음을 통해 공유


KQL(Kusto 쿼리 언어) 그래프 의미 체계에 대한 모범 사례

이 문서에서는 다양한 사용 사례 및 시나리오에 대해 KQL에서 그래프 의미 체계 기능을 효과적이고 효율적으로 사용하는 방법을 설명합니다. 구문 및 연산자를 사용하여 그래프를 만들고 쿼리하는 방법과 다른 KQL 기능 및 함수와 통합하는 방법을 보여 줍니다. 또한 메모리 또는 성능 제한을 초과하는 그래프를 만들거나 부적합하거나 호환되지 않는 필터, 프로젝션 또는 집계를 적용하는 것과 같은 일반적인 문제 또는 오류를 방지할 수 있습니다.

그래프 크기

make-graph 연산자는 그래프의 메모리 내 표현을 만듭니다. 그래프 구조 자체와 해당 속성으로 구성됩니다. 그래프를 만들 때 적절한 필터, 프로젝션 및 집계를 사용하여 관련 노드와 에지 및 해당 속성만 선택합니다.

다음 예제에서는 노드와 에지 및 해당 속성의 수를 줄이는 방법을 보여 줍니다. 이 시나리오에서 Bob은 관리자를 Alice에서 Eve로 변경했으며 사용자는 조직에 대한 그래프의 최신 상태만 보고 싶어 합니다. 그래프의 크기를 줄이기 위해 노드는 먼저 조직 속성에 의해 필터링된 다음 프로젝트 어웨이 연산자를 사용하여 그래프에서 속성이 제거됩니다. 에지도 마찬가지입니다. 그런 다음 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

출력

직원 topManager
Bob Mallory

그래프의 마지막으로 알려진 상태

그래프 크기 예제에서는 연산자 및 arg_max 집계 함수를 사용하여 summarize 그래프 가장자리의 마지막으로 알려진 상태를 가져오는 방법을 보여 줍니다. 마지막으로 알려진 상태를 가져오는 것은 계산 집약적인 작업입니다.

다음과 같이 쿼리 성능을 향상시키기 위해 구체화된 뷰를 만드는 것이 좋습니다.

  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. 구체화된 뷰의 구체화된 구성 요소만 사용되고 추가 필터 및 프로젝션이 적용되도록 하는 두 개의 함수를 만듭니다.

    .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

출력

직원 topManager
Bob Dave

여러 노드 및 에지 형식 처리

경우에 따라 여러 노드 형식으로 구성된 그래프를 사용하여 시계열 데이터를 컨텍스트화해야 합니다. 이 시나리오를 처리하는 한 가지 방법은 정식 모델로 표현되는 범용 속성 그래프를 만드는 것입니다.

경우에 따라 여러 노드 형식이 있는 그래프를 사용하여 시계열 데이터를 컨텍스트화해야 할 수 있습니다. 다음과 같이 정식 모델을 기반으로 하는 범용 속성 그래프를 만들어 문제에 접근할 수 있습니다.

  • 노드
    • nodeId(string)
    • label(string)
    • 속성(동적)
  • 가장자리
    • source(string)
    • destination(string)
    • label(string)
    • 속성(동적)

다음 예제에서는 데이터를 정식 모델로 변환하는 방법과 쿼리하는 방법을 보여줍니다. 그래프의 노드 및 가장자리에 대한 기본 테이블에는 스키마가 다릅니다.

이 시나리오에는 장비가 잘 작동하지 않는 이유와 장비를 수정할 책임이 있는 팩터리 관리자가 포함됩니다. 관리자는 프로덕션 현장의 자산 그래프와 매일 변경되는 유지 관리 직원 계층 구조를 결합하는 그래프를 사용하기로 결정합니다.

다음 그래프는 속도, 온도 및 압력과 같은 자산과 시계열 간의 관계를 보여 줍니다. 운영자와 펌프와 같은 자산은 운영 에지를 통해 연결됩니다. 운영자 자체는 관리에 보고합니다.

속성 그래프 시나리오에 대한 인포그래픽입니다.

이러한 엔터티에 대한 데이터는 클러스터에 직접 저장하거나 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

그래프 일치의 프로젝션은 온도 센서가 지정된 날짜에 변칙을 표시한 정보를 출력합니다. 그것은 궁극적으로 Mallory에보고 이브에 의해 운영되었다. 이 정보를 통해 공장 관리자는 이브와 잠재적으로 Mallory에게 연락하여 변칙을 더 잘 이해할 수 있습니다.