Meilleures pratiques pour les requêtes Langage de requête Kusto
S’applique à : ✅Microsoft Fabric✅Azure Data Explorer✅Azure Monitor✅Microsoft Sentinel
Voici plusieurs meilleures pratiques à suivre pour accélérer l’exécution de votre requête.
Bref
Action | Utiliser | N’utilisez pas | Notes |
---|---|---|---|
Réduire la quantité de données interrogées | Utilisez des mécanismes tels que l’opérateur where pour réduire la quantité de données en cours de traitement. |
Pour plus d’informations sur les moyens efficaces de réduire la quantité de données en cours de traitement, consultez Réduire la quantité de données en cours de traitement. | |
Éviter d’utiliser des références qualifiées redondantes | Lorsque vous référencez des entités locales, utilisez le nom non qualifié. | Pour plus d’informations, consultez Éviter d’utiliser des références qualifiées redondantes. | |
datetime colonnes |
Utilisez le type de données datetime . |
N’utilisez pas le long type de données. |
Dans les requêtes, n’utilisez pas de fonctions de conversion de temps Unix, telles que unixtime_milliseconds_todatetime() . Utilisez plutôt des stratégies de mise à jour pour convertir le temps Unix en type de données pendant l’ingestion datetime . |
Opérateurs de chaîne | Utiliser l’opérateur has . |
N’utilisez pas contains |
Lorsque vous recherchez des jetons complets, has fonctionne mieux, car il ne recherche pas de sous-chaînes. |
Opérateurs respectant la casse | Utiliser == . |
N’utilisez pas =~ . |
Utilisez des opérateurs respectant la casse quand c’est possible. |
Utiliser in . |
N’utilisez pas in~ . |
||
Utiliser contains_cs . |
N’utilisez pas contains . |
L’utilisation est préférée àcontains_cs contains / .has /has_cs |
|
Recherche de texte | Examinez une colonne spécifique. | N’utilisez pas * . |
* effectue une recherche en texte intégral dans toutes les colonnes. |
Extraire les champs d’objets dynamiques dans plusieurs millions de lignes | Matérialisez votre colonne au moment de l’ingestion si la plupart de vos requêtes extraient des champs d’objets dynamiques dans des millions de lignes. | Avec cette méthode, vous ne payez qu’une seule fois pour l’extraction de colonnes. | |
Rechercher les clés/valeurs rares dans des objets dynamiques | Utiliser MyTable | where DynamicColumn has "Rare value" | where DynamicColumn.SomeKey == "Rare value" . |
N’utilisez pas MyTable | where DynamicColumn.SomeKey == "Rare value" . |
Avec cette méthode, vous filtrez la plupart des enregistrements et effectuez uniquement l’analyse JSON sur le reste. |
Instruction let avec une valeur que vous utilisez plusieurs fois |
Utilisez la fonction materialize(). | Pour plus d’informations sur l’utilisation de la fonction materialize() , consultez materialize(). Pour plus d’informations, consultez Optimiser les requêtes qui utilisent des expressions nommées. |
|
Appliquer des conversions de types sur plus d’un milliard d’enregistrements | Remodelez votre requête pour réduire la quantité de données chargées dans la conversion. | Ne convertissez pas de grandes quantités de données si vous pouvez l’éviter. | |
Nouvelles requêtes | Utilisez limit [small number] ou count à la fin. |
L’exécution de requêtes indépendantes sur des jeux de données inconnus peut générer un retour de gigaoctets de résultats, ce qui entraîne une réponse lente et un environnement occupé. | |
Comparaisons ne respectant pas la casse | Utiliser Col =~ "lowercasestring" . |
N’utilisez pas tolower(Col) == "lowercasestring" . |
|
Comparer des données déjà en minuscules (ou en majuscules) | Col == "lowercasestring" (ou Col == "UPPERCASESTRING" ). |
Évitez d’utiliser des comparaisons ne respectant pas la casse. | |
Filtrage sur les colonnes | Filtrez sur une colonne de table. | Ne filtrez pas sur une colonne calculée. | |
Utilisez T | where predicate(*Expression*) . |
N’utilisez pas T | extend _value = *Expression* | where predicate(_value) |
||
Opérateur summarize | Utilisez la clé hint.shufflekey=<key> lorsque l’opérateur group by keys summarize a une cardinalité élevée. |
La cardinalité élevée est idéalement supérieure à un million. | |
Opérateur de jointure | Sélectionnez la table avec les lignes les plus rares en tant que première (requête la plus à gauche). | ||
Utilisez in plutôt que semi-gauche join pour le filtrage par une seule colonne. |
|||
Joindre des clusters à l’autre | Exécutez la requête du côté « droit » de la jointure dans des environnements distants, tels que des clusters ou des entrepôts d’événements, où se trouvent la plupart des données. | ||
Jointure lorsque le côté gauche est petit et que le côté droit est grand | Utilisez hint.strategy=broadcast. | Small fait référence à jusqu’à 100 mégaoctets (Mo) de données. | |
Jointure lorsque le côté droit est petit et que le côté gauche est grand | Utiliser l’opérateur de recherche au lieu de l’opérateur join |
Si le côté droit de la recherche est supérieur à plusieurs dizaines de Mo, la requête échoue. | |
Joindre lorsque les deux côtés sont trop grands | Utilisez hint.shufflekey=<key>. | Utilisez lorsque la clé de jointure présente une cardinalité élevée. | |
Extraire des valeurs d’une colonne contenant des chaînes partageant les mêmes format ou modèle | Utilisez l’opérateur d’analyse. | N’utilisez pas plusieurs instructions extract() . |
Par exemple, des valeurs telles que "Time = <time>, ResourceId = <resourceId>, Duration = <duration>, ...." . |
Fonction extract() | Utilisez-la lorsque les chaînes analysées ne suivent pas toutes les mêmes format ou modèle. | Extrayez les valeurs requises à l’aide d’une expression régulière. | |
Fonction materialize() | Envoyez (push) tous les opérateurs possibles qui réduisent le jeu de données matérialisé et conservent toujours la sémantique de la requête. | Par exemple, filtrez, ou projetez uniquement les colonnes requises. Pour plus d’informations, consultez Optimiser les requêtes qui utilisent des expressions nommées. | |
Utiliser des vues matérialisées | Utilisez des vues matérialisées pour stocker les agrégations couramment utilisées. Préférez utiliser la materialized_view() fonction pour interroger la partie matérialisée uniquement. |
materialized_view('MV') |
Réduire la quantité de données en cours de traitement
Les performances d’une requête dépendent directement de la quantité de données dont elle a besoin pour traiter. Moins les données sont traitées, plus la requête est plus rapide (et moins elle consomme de ressources). Par conséquent, la meilleure pratique la plus importante consiste à structurer la requête de manière à réduire la quantité de données en cours de traitement.
Remarque
Dans la discussion suivante, il est important d’avoir à l’esprit le concept de sélectivité de filtre. La sélectivité est le pourcentage d’enregistrements filtrés lors du filtrage par un prédicat. Un prédicat hautement sélectif signifie que seuls quelques enregistrements restent après l’application du prédicat, réduisant ainsi la quantité de données qui doivent ensuite être traitées efficacement.
Ordre d’importance :
Seules les tables de référence dont les données sont nécessaires par la requête. Par exemple, lorsque vous utilisez l’opérateur
union
avec des références de table générique, il est préférable d’un point de vue de performances de référencer uniquement une poignée de tables, au lieu d’utiliser un caractère générique (*
) pour référencer toutes les tables, puis de filtrer les données à l’aide d’un prédicat sur le nom de la table source.Tirez parti de l’étendue des données d’une table si la requête est pertinente uniquement pour une étendue spécifique. La fonction table() offre un moyen efficace d’éliminer les données en les définissant en fonction de la stratégie de mise en cache (paramètre DataScope ).
Appliquez l’opérateur
where
de requête immédiatement après les références de table.Lorsque vous utilisez l’opérateur
where
de requête, l’ordre dans lequel vous placez les prédicats, que vous utilisiez un opérateur uniquewhere
ou plusieurs opérateurs consécutifswhere
, puisse avoir un effet significatif sur les performances de la requête.Appliquez d’abord des prédicats de partition entière. Cela signifie que les prédicats qui utilisent la fonction extent_id() et la fonction extent_tags() doivent être appliqués en premier. En outre, lorsque vous avez des prédicats sélectifs qui réduisent les données à des partitions spécifiques, ils doivent d’abord être appliqués.
Ensuite, appliquez des prédicats qui agissent sur
datetime
les colonnes de table. Kusto inclut un index efficace sur ces colonnes, éliminant souvent complètement les partitions de données entières sans avoir à accéder à ces partitions.Ensuite, appliquez des prédicats qui agissent sur et
dynamic
desstring
colonnes, en particulier de tels prédicats qui s’appliquent au niveau du terme. Commandez les prédicats par la sélectivité. Par exemple, la recherche d’un ID d’utilisateur lorsqu’il existe des millions d’utilisateurs est très sélective et implique généralement une recherche de terme, pour laquelle l’index est très efficace.Ensuite, appliquez des prédicats sélectifs et basés sur des colonnes numériques.
Enfin, pour les requêtes qui analysent les données d’une colonne de table (par exemple, pour les prédicats tels que
contains
"@!@!"
, qui n’ont aucun terme et ne bénéficient pas de l’indexation), commandez les prédicats de sorte que ceux qui analysent les colonnes avec moins de données sont d’abord. Cela réduit la nécessité de décompresser et d’analyser de grandes colonnes.
Éviter d’utiliser des références qualifiées redondantes
Référencer des entités telles que des tables et des vues matérialisées par nom.
Par exemple, la table T
peut être référencée comme simplement T
(nom non qualifié) ou à l’aide d’un qualificateur de base de données (par exemple, database("DB").T
lorsque la table se trouve dans une base de données appeléeDB
) ou à l’aide d’un nom complet (par exemple). cluster("<serviceURL>").database("DB").T
Par exemple, la table T
peut être référencée comme simplement T
(nom non qualifié) ou à l’aide d’un qualificateur de base de données (par exemple, database("DB").T
lorsque la table se trouve dans une base de données appeléeDB
) ou à l’aide d’un nom complet (par exemple). cluster("X.Y.kusto.windows.net").database("DB").T
Il est recommandé d’éviter d’utiliser des qualifications de nom lorsqu’elles sont redondantes, pour les raisons suivantes :
Les noms non qualifiés sont plus faciles à identifier (pour un lecteur humain) comme appartenant à la base de données dans l’étendue.
Le référencement d’entités de base de données dans l’étendue est toujours au moins aussi rapide, et dans certains cas beaucoup plus rapide, puis les entités qui appartiennent à d’autres bases de données.
Cela est particulièrement vrai lorsque ces bases de données se trouvent dans un autre cluster.
Cela est particulièrement vrai lorsque ces bases de données se trouvent dans un autre Eventhouse.
L’évitement des noms qualifiés aide le lecteur à faire la bonne chose.
Remarque
Cela ne signifie pas que les noms qualifiés sont incorrects pour les performances. En fait, Kusto est en mesure dans la plupart des cas d’identifier quand un nom complet fait référence à une entité qui appartient à la base de données dans l’étendue et au « court-circuit » de la requête afin qu’elle ne soit pas considérée comme une requête inter-cluster. Toutefois, nous vous déconseillons de vous appuyer sur ce problème quand cela n’est pas nécessaire.
Remarque
Cela ne signifie pas que les noms qualifiés sont incorrects pour les performances. En fait, Kusto est en mesure dans la plupart des cas d’identifier quand un nom complet fait référence à une entité appartenant à la base de données dans l’étendue. Toutefois, nous vous déconseillons de vous appuyer sur ce problème quand cela n’est pas nécessaire.