Рекомендации по семантике графа язык запросов Kusto (KQL)
В этой статье объясняется, как использовать функцию семантики графа в KQL эффективно и эффективно для различных вариантов использования и сценариев. В нем показано, как создавать и запрашивать графы с синтаксисом и операторами, а также как интегрировать их с другими функциями и функциями KQL. Кроме того, пользователи могут избежать распространенных ошибок или ошибок, таких как создание графов, превышающих ограничения памяти или производительности, а также применение неподходящих или несовместимых фильтров, проекций или агрегатов.
Размер графа
Оператор make-graph создает представление графа в памяти. Он состоит из самой структуры графа и ее свойств. При создании графа используйте соответствующие фильтры, проекции и агрегаты, чтобы выбрать только соответствующие узлы и края и их свойства.
В следующем примере показано, как уменьшить количество узлов и ребер и их свойств. В этом сценарии Боб изменил менеджера с Алисы на Ева, и пользователь хочет увидеть последнее состояние графа для своей организации. Чтобы уменьшить размер графа, узлы сначала фильтруются по свойству организации, а затем свойство удаляется из графа с помощью оператора 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
Выходные данные
Сотрудника | topManager |
---|---|
Борис | Мэллори |
Последнее известное состояние графа
В примере графа показано, как получить последнее известное состояние ребер графа с помощью summarize
оператора и arg_max
функции агрегирования. Получение последнего известного состояния — это операция с интенсивным вычислением.
Рассмотрите возможность создания материализованного представления для повышения производительности запроса следующим образом:
Создайте таблицы, имеющие некоторое представление о версии в рамках модели. Рекомендуется использовать
datetime
столбец, который можно использовать позже для создания временных рядов графа..create table employees (organization: string, name:string, stateOfEmployment:string, properties:dynamic, modificationDate:datetime) .create table reportsTo (employee:string, manager:string, modificationDate: datetime)
Создайте материализованное представление для каждой таблицы и используйте функцию агрегирования 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 }
Создайте две функции, которые гарантируют, что применяются только материализованные компоненты материализованного представления, а также применяются дополнительные фильтры и проекции.
.create function currentEmployees () { materialized_view('employees_MV') | where stateOfEmployment == "employed" } .create function reportsTo_lastKnownState () { materialized_view('reportsTo_MV') | project-away modificationDate }
Результирующий запрос с помощью материализованных делает запрос более быстрым и эффективным для более крупных графов. Кроме того, он включает более высокий параллелизм и более низкие запросы задержки для последнего состояния графа. Пользователь по-прежнему может запрашивать журнал графов на основе таблиц employees и 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 года.
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 |
---|---|
Борис | Dave |
Работа с несколькими типами узлов и ребер
Иногда требуется контекстуализировать данные временных рядов с графом, состоящим из нескольких типов узлов. Одним из способов обработки этого сценария является создание графа свойств общего назначения, представленного канонической моделью.
Иногда может потребоваться контекстуализировать данные временных рядов с графом с несколькими типами узлов. Вы можете приблизиться к проблеме, создав граф свойств общего назначения, основанный на канонической модели, например следующей.
- Узлов
- nodeId (string)
- label (string)
- properties (dynamic)
- Края
- source (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-match в этом экземпляре , где сокращает теги до тех, которые имеют аномалию и работали в определенный день.
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 |
---|---|---|---|
Температура | Pump | Ева | Мэллори |
Проекция в граф-сопоставлении выводит сведения о том, что датчик температуры показал аномалию в указанный день. Она была оперирована Евом, который в конечном счете сообщает Мэллори. С этой информацией менеджер фабрики может обратиться к Евам и потенциально Mallory, чтобы получить лучшее понимание аномалии.
Связанный контент
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по