Best practices voor Kusto-querytaal (KQL) grafieksemantiek (preview)
Waarschuwing
Deze functie is momenteel beschikbaar als preview-versie en kan worden gewijzigd. De semantiek en syntaxis van de grafiekfunctie kunnen worden gewijzigd voordat ze worden vrijgegeven als algemeen beschikbaar.
In dit artikel wordt uitgelegd hoe u de functie grafieksemantiek in KQL effectief en efficiënt kunt gebruiken voor verschillende gebruiksscenario's en scenario's. Het laat zien hoe u grafieken maakt en opvraagt met de syntaxis en operators, en hoe u deze integreert met andere KQL-functies en -functies. Het helpt gebruikers ook veelvoorkomende valkuilen of fouten te voorkomen, zoals het maken van grafieken die de geheugen- of prestatielimieten overschrijden, of het toepassen van ongeschikte of incompatibele filters, projecties of aggregaties.
Grootte van grafiek
Met de operator grafiek maken wordt een in-memory weergave van een grafiek gemaakt. Het bestaat uit de grafiekstructuur zelf en de bijbehorende eigenschappen. Gebruik bij het maken van een grafiek de juiste filters, projecties en aggregaties om alleen de relevante knooppunten en randen en hun eigenschappen te selecteren.
In het volgende voorbeeld ziet u hoe u het aantal knooppunten en randen en hun eigenschappen kunt verminderen. In dit scenario is Bob van manager veranderd van Alice in Eve en wil de gebruiker alleen de meest recente status van de grafiek voor de organisatie zien. Om de grafiek kleiner te maken, worden de knooppunten eerst gefilterd op de organisatie-eigenschap en vervolgens wordt de eigenschap uit de grafiek verwijderd met behulp van de operator project-away. Hetzelfde gebeurt voor randen. Vat vervolgens de operator samen met arg_max wordt gebruikt om de laatst bekende status van de grafiek op te halen.
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
Uitvoer
Werknemer | topManager |
---|---|
Bob | Mallory |
Laatst bekende status van de grafiek
In het voorbeeld Grootte van grafiek is gedemonstreerd hoe u de laatst bekende status van de randen van een grafiek opgeeft met behulp van summarize
de operator en de arg_max
aggregatiefunctie. Het verkrijgen van de laatst bekende status is een rekenintensieve bewerking.
U kunt als volgt een gerealiseerde weergave maken om de queryprestaties te verbeteren:
Maak tabellen met een bepaald begrip van de versie als onderdeel van hun model. U wordt aangeraden een
datetime
kolom te gebruiken die u later kunt gebruiken om een grafiektijdreeks te maken..create table employees (organization: string, name:string, stateOfEmployment:string, properties:dynamic, modificationDate:datetime) .create table reportsTo (employee:string, manager:string, modificationDate: datetime)
Maak een gerealiseerde weergave voor elke tabel en gebruik de aggregatiefunctie arg_max om de laatst bekende status van werknemers en de relatie reportsTo te bepalen.
.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 }
Maak twee functies die ervoor zorgen dat alleen het gerealiseerde onderdeel van de gerealiseerde weergave wordt gebruikt en dat aanvullende filters en projecties worden toegepast.
.create function currentEmployees () { materialized_view('employees_MV') | where stateOfEmployment == "employed" } .create function reportsTo_lastKnownState () { materialized_view('reportsTo_MV') | project-away modificationDate }
De resulterende query met behulp van gerealiseerd maakt de query sneller en efficiënter voor grotere grafieken. Het maakt ook hogere gelijktijdigheid en lagere latentiequery's mogelijk voor de meest recente status van de grafiek. De gebruiker kan nog steeds een query uitvoeren op de grafiekgeschiedenis op basis van de werknemers en reportsTo-tabellen , indien nodig
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
Tijdreizen in grafiek
In sommige scenario's moet u gegevens analyseren op basis van de status van een grafiek op een specifiek tijdstip. Grafiektijdreizen maken gebruik van een combinatie van tijdfilters en samenvattingen met behulp van de aggregatiefunctie arg_max.
Met de volgende KQL-instructie maakt u een functie met een parameter die het interessante tijdstip voor de grafiek definieert. Er wordt een kant-en-klare grafiek geretourneerd.
.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
}
Met de functie kan de gebruiker een query maken om de topmanager van Bob op te halen op basis van de grafiek in juni 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
Uitvoer
Werknemer | topManager |
---|---|
Bob | Dave |
Omgaan met meerdere knooppunt- en edge-typen
Soms is het nodig om tijdreeksgegevens te contextualiseren met een grafiek die uit meerdere knooppunttypen bestaat. Een manier om dit scenario te verwerken, is het maken van een eigenschappengrafiek voor algemeen gebruik die wordt vertegenwoordigd door een canoniek model.
Soms moet u mogelijk tijdreeksgegevens contextualiseren met een grafiek met meerdere knooppunttypen. U kunt het probleem oplossen door een eigenschappengrafiek voor algemeen gebruik te maken die is gebaseerd op een canoniek model, zoals hieronder.
- Knooppunten
- nodeId (tekenreeks)
- label (tekenreeks)
- eigenschappen (dynamisch)
- Randen
- bron (tekenreeks)
- bestemming (tekenreeks)
- label (tekenreeks)
- eigenschappen (dynamisch)
In het volgende voorbeeld ziet u hoe u de gegevens transformeert in een canoniek model en hoe u er query's op kunt uitvoeren. De basistabellen voor de knooppunten en randen van de grafiek hebben verschillende schema's.
In dit scenario is een fabrieksmanager betrokken die wil weten waarom apparatuur niet goed werkt en wie verantwoordelijk is voor het repareren ervan. De manager besluit een grafiek te gebruiken die de assetgrafiek van de productievloer combineert met de hiërarchie van onderhoudspersoneel die elke dag wordt gewijzigd.
In de volgende grafiek ziet u de relaties tussen assets en hun tijdreeks, zoals snelheid, temperatuur en druk. De operatoren en de activa, zoals pomp, zijn verbonden via de bedieningsrand . De operators rapporteren zelf aan het management.
De gegevens voor deze entiteiten kunnen rechtstreeks in uw cluster worden opgeslagen of met behulp van queryfederatie worden verkregen naar een andere service, zoals Azure Cosmos DB, Azure SQL of Azure Digital Twin. Ter illustratie van het voorbeeld worden de volgende tabelgegevens gemaakt als onderdeel van de query:
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"
];
De werknemers, sensoren en andere entiteiten en relaties delen geen canoniek gegevensmodel. U kunt de samenvoegoperator gebruiken om de gegevens te combineren en te canoniseren.
Met de volgende query worden de sensorgegevens samengevoegd met de tijdreeksgegevens om de sensoren te vinden die abnormale metingen hebben. Vervolgens wordt een projectie gebruikt om een gemeenschappelijk model voor de grafiekknooppunten te maken.
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));
De randen worden op een vergelijkbare manier getransformeerd.
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" );
Met de gecanoniseerde knooppunten en randengegevens kunt u als volgt een grafiek maken met behulp van de operator grafiek maken:
let graph = edges
| make-graph source --> destination with nodes on nodeId;
Zodra het pad is gemaakt, definieert u het padpatroon en projectt u de vereiste informatie. Het patroon begint bij een tagknooppunt, gevolgd door een rand met variabele lengte naar een asset. Deze asset wordt beheerd door een operator die rapporteert aan een topmanager via een rand met variabele lengte, genaamd reportsTo. De sectie beperkingen van de operator graph-match, in dit geval , vermindert de tags tot de tags die een anomalie hebben en op een specifieke dag zijn uitgevoerd.
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)
Uitvoer
tagWithAnomaly | impactedAsset | operatorName | responsibleManager |
---|---|---|---|
temperatuur | Pomp | Eve | Mallory |
De projectie in grafiekovereenkomst levert de informatie uit dat de temperatuursensor een anomalie heeft vertoond op de opgegeven dag. Het werd bediend door Eve die uiteindelijk rapporteert aan Mallory. Met deze informatie kan de fabrieksmanager contact opnemen met Eve en mogelijk Mallory om een beter inzicht te krijgen in de anomalie.