Limites de requête

Kusto est un moteur de requête ad hoc qui héberge des jeux de données volumineux et tente de satisfaire les requêtes en conservant toutes les données pertinentes en mémoire. Il existe un risque inhérent au fait que les requêtes monopolisent les ressources de service sans limites. Kusto fournit plusieurs protections intégrées sous la forme de limites de requête par défaut. Si vous envisagez de supprimer ces limites, déterminez d’abord si cela constitue un réel avantage.

Limite sur la concurrence des demandes

La concurrence des demandes est une limite qu’un cluster impose sur plusieurs demandes exécutées en même temps.

  • La valeur par défaut de la limite dépend de la référence SKU sur laquelle le cluster s’exécute, et est calculée comme suit : Cores-Per-Node x 10.
    • Par exemple, pour un cluster configuré sur la référence SKU D14v2, où chaque ordinateur a 16 vCores, la limite par défaut est 16 cores x10 = 160.
  • La valeur par défaut peut être modifiée en configurant la stratégie de limites de taux de demandes du groupe de charge de travail default.
    • Le nombre réel de demandes pouvant s’exécuter simultanément sur un cluster dépend de différents facteurs. Les facteurs les plus dominants sont la référence SKU du cluster, les ressources disponibles du cluster et les modèles d’usage. La stratégie peut être configurée en fonction des tests de charge effectués sur des modèles d’usage de type production.

Pour plus d’informations, consultez Optimiser pour une haute simultanéité avec Azure Data Explorer.

Limite de la taille du jeu de résultats (troncation des résultats)

La troncation des résultats est une limite définie par défaut sur le jeu de résultats retourné par la requête. Kusto limite le nombre d’enregistrements retournés au client à 500 000 et la taille globale des données pour ces enregistrements à 64 Mo. Lorsque l’une ou l’autre de ces limites est dépassée, la requête échoue avec un « échec partiel de la requête ». Le dépassement de la taille globale des données génère une exception avec le message suivant :

The Kusto DataEngine has failed to execute a query: 'Query result set has exceeded the internal data size limit 67108864 (E_QUERY_RESULT_SET_TOO_LARGE).'

Le dépassement du nombre d’enregistrements aboutit à un échec avec une exception qui indique :

The Kusto DataEngine has failed to execute a query: 'Query result set has exceeded the internal record count limit 500000 (E_QUERY_RESULT_SET_TOO_LARGE).'

Il existe plusieurs stratégies pour gérer cette erreur.

  • Réduisez la taille du jeu de résultats en modifiant la requête pour qu’elle retourne uniquement des données intéressantes. Cette stratégie est utile lorsque la requête initiale ayant échoué est trop « large ». Par exemple, la requête ne projette pas les colonnes de données qui ne sont pas nécessaires.
  • Réduisez la taille du jeu de résultats en décalant le traitement après requête, tel que les agrégations, dans la requête elle-même. La stratégie est utile dans les scénarios où la sortie de la requête est acheminée vers un autre système de traitement, qui effectue ensuite d’autres agrégations.
  • Basculez des requêtes à l’utilisation de l’exportation de données lorsque vous souhaitez exporter de grands jeux de données à partir du service.
  • Demandez au service de supprimer cette limite de requête à l’aide des instructions set listées ci-dessous ou des indicateurs disponibles dans les propriétés de demande du client.

Les méthodes de réduction de la taille de jeu de résultats produite par la requête sont les suivantes :

Vous pouvez désactiver la troncation des résultats à l’aide de l’option de demande notruncation. Nous vous recommandons de continuer à mettre en place une certaine forme de limitation.

Par exemple :

set notruncation;
MyTable | take 1000000

Il est également possible d’avoir un contrôle plus fin sur la troncation des résultats en définissant la valeur de truncationmaxsize (taille de données maximale en octets, 64 Mo par défaut) et truncationmaxrecords (nombre maximal d’enregistrements, 500 000 par défaut). Par exemple, la requête suivante définit la troncation des résultats sur 1 105 enregistrements ou 1 Mo, selon la valeur dépassée.

set truncationmaxsize=1048576;
set truncationmaxrecords=1105;
MyTable | where User=="UserId1"

Si vous supprimez la limite de troncation des résultats, cela signifie que vous avez l’intention de déplacer les données en bloc en dehors de Kusto.

Vous pouvez supprimer la limite de troncation des résultats à des fins d’exportation à l’aide de la commande .export ou d’une agrégation ultérieure. Si vous choisissez l’agrégation ultérieure, envisagez l’agrégation à l’aide de Kusto.

Kusto fournit un certain nombre de bibliothèques clientes qui peuvent gérer des résultats « infiniment volumineux » en les diffusant à l’appelant. Utilisez l’une de ces bibliothèques et configurez-la en mode de streaming. Par exemple, utilisez le client .NET Framework (Microsoft.Azure.Kusto.Data) et définissez la propriété de streaming de la chaîne de connexion sur true, ou utilisez l’appel ExecuteQueryV2Async() qui transmet toujours les résultats. Pour obtenir un exemple d’utilisation de ExecuteQueryV2Async(), consultez l’application HelloKustoV2 .

L’exemple d’application pour l’ingestion en streaming avec C# peut également vous être utile.

La troncation des résultats est appliquée par défaut, pas uniquement au flux de résultats retourné au client. Elle est également appliquée par défaut aux sous-requêtes qu’un cluster émet sur un autre cluster dans une requête entre clusters, avec des effets similaires.

Définition de plusieurs propriétés de troncation de résultats

Les éléments suivants s’appliquent lors de l’utilisation d’instructions set et/ou lors de la spécification d’indicateurs dans les propriétés de demande du client.

  • Si notruncation est défini et que truncationmaxsize, truncationmaxrecords ou query_take_max_records sont aussi définis - notruncation est ignoré.
  • Si truncationmaxsize, truncationmaxrecords et/ou query_take_max_records sont définis plusieurs fois, la valeur inférieure de chaque propriété s’applique.

Limite de mémoire consommée par les opérateurs de requête (E_RUNAWAY_QUERY)

Kusto limite la mémoire que chaque opérateur de requête peut consommer pour se protéger contre les requêtes « runaway ». Cette limite peut être atteinte par certains opérateurs de requête, tels que join et summarize, qui fonctionnent en conservant des données significatives en mémoire. Par défaut, la limite est de 5 Go (par nœud de cluster), et elle peut être augmentée en définissant l’option maxmemoryconsumptionperiteratorde demande :

set maxmemoryconsumptionperiterator=68719476736;
MyTable | summarize count() by Use

Lorsque cette limite est atteinte, un échec de requête partiel est émis avec un message qui inclut le texte E_RUNAWAY_QUERY.

The ClusterBy operator has exceeded the memory budget during evaluation. Results may be incorrect or incomplete E_RUNAWAY_QUERY.

The DemultiplexedResultSetCache operator has exceeded the memory budget during evaluation. Results may be incorrect or incomplete (E_RUNAWAY_QUERY).

The ExecuteAndCache operator has exceeded the memory budget during evaluation. Results may be incorrect or incomplete (E_RUNAWAY_QUERY).

The HashJoin operator has exceeded the memory budget during evaluation. Results may be incorrect or incomplete (E_RUNAWAY_QUERY).

The Sort operator has exceeded the memory budget during evaluation. Results may be incorrect or incomplete (E_RUNAWAY_QUERY).

The Summarize operator has exceeded the memory budget during evaluation. Results may be incorrect or incomplete (E_RUNAWAY_QUERY).

The TopNestedAggregator operator has exceeded the memory budget during evaluation. Results may be incorrect or incomplete (E_RUNAWAY_QUERY).

The TopNested operator has exceeded the memory budget during evaluation. Results may be incorrect or incomplete (E_RUNAWAY_QUERY).

Si maxmemoryconsumptionperiterator est défini plusieurs fois, par exemple dans les propriétés de demande client et en utilisant une instruction set, la valeur inférieure est appliquée.

Une limite supplémentaire qui peut déclencher un E_RUNAWAY_QUERY échec de requête partiel est une limite sur la taille maximale cumulée des chaînes détenues par un opérateur unique. Cette limite ne peut pas être remplacée par l’option de requête ci-dessus :

Runaway query (E_RUNAWAY_QUERY). Aggregation over string column exceeded the memory budget of 8GB during evaluation.

Lorsque cette limite est dépassée, l’opérateur de requête approprié est probablement , joinsummarizeou make-series. Pour contourner la limite, vous devez modifier la requête afin d’utiliser la stratégie de requête aléatoire . (Cela est également susceptible d’améliorer les performances de la requête.)

Dans tous les cas de , une option supplémentaire (au-delà de E_RUNAWAY_QUERYl’augmentation de la limite en définissant l’option de requête et en modifiant la requête pour utiliser une stratégie de lecture aléatoire) consiste à basculer vers l’échantillonnage. Les deux requêtes ci-dessous montrent comment effectuer l’échantillonnage. La première requête est un échantillonnage statistique effectuée avec un générateur de nombres aléatoires. La deuxième requête est l’échantillonnage déterministe, effectué en hachant une colonne du jeu de données, généralement un ID.

T | where rand() < 0.1 | ...

T | where hash(UserId, 10) == 1 | ...

Limite de mémoire par nœud

La mémoire maximale par requête par nœud est une autre limite utilisée pour la protection contre les pertes de contrôle de requête. Cette limite, représentée par l’option de demande max_memory_consumption_per_query_per_node, définit une limite supérieure sur la quantité de mémoire qui peut être utilisée sur un seul nœud pour une requête spécifique.

set max_memory_consumption_per_query_per_node=68719476736;
MyTable | ...

Si max_memory_consumption_per_query_per_node est défini plusieurs fois, par exemple dans les propriétés de demande client et en utilisant une instruction set, la valeur inférieure est appliquée.

Si la requête utilise des opérateurs summarize, join ou make-series, vous pouvez utiliser la stratégie de requête aléatoire pour réduire la sollicitation de la mémoire sur une même machine.

Limiter l’expiration de l’exécution

Le délai d’expiration du serveur est un délai d’attente côté service qui est appliqué à toutes les demandes. Le délai d’exécution des requêtes (requêtes et commandes de gestion) est appliqué à plusieurs points du Kusto :

  • Bibliothèque cliente (si utilisée)
  • Point de terminaison de service qui accepte la demande
  • Moteur de service qui traite la demande

Par défaut, le délai d’expiration est défini sur quatre minutes pour les requêtes et sur 10 minutes pour les commandes de gestion. Cette valeur peut être augmentée si nécessaire (elle est limitée à une heure).

  • Différents outils clients prennent en charge la modification du délai d’expiration dans le cadre de leurs paramètres globaux ou par connexion. Par exemple, dans Kusto. Explorer, utilisez Options d’outils>*>Connexions>Délai d’expiration du serveur de requête.
  • Sur le plan programmatique, les SDK prennent en charge la définition du délai d’expiration via la servertimeout propriété . Par exemple, dans le KIT de développement logiciel (SDK) .NET, cela s’effectue via une propriété de demande cliente, en définissant une valeur de type System.TimeSpan.

Remarques sur les délais d’expiration

  • Côté client, le délai d’expiration est appliqué à partir de la création de la demande jusqu’au moment où la réponse commence à arriver au client. Le temps nécessaire à la lecture de la charge utile sur le client n’est pas pris en compte dans le délai d’expiration. Il dépend de la vitesse à laquelle l’appelant extrait les données du flux.
  • De même, côté client, la valeur de délai d’expiration réelle utilisée est légèrement supérieure à la valeur de délai d’expiration du serveur demandée par l’utilisateur. Cette différence consiste à autoriser les latences du réseau.
  • Pour utiliser automatiquement le délai d’expiration de demande maximal autorisé, définissez la propriété de demande du client norequesttimeout sur true.

Notes

Consultez Définir des limites de délai d’expiration pour obtenir un guide pas à pas sur la façon de définir des délais d’expiration dans l’interface utilisateur web Azure Data Explorer, Kusto.Explorer, Kusto.Cli, Power BI et lors de l’utilisation d’un KIT de développement logiciel (SDK).

Limite sur l’utilisation des ressources processeur des requêtes

Kusto vous permet d’exécuter des requêtes et d’utiliser autant de ressources processeur que le cluster. Il tente d’effectuer un aller-retour (round robin) juste entre les requêtes si plusieurs sont en cours d’exécution. Cette méthode offre les meilleures performances pour les fonctions définies par la requête. À d’autres moments, vous avez la possibilité de limiter les ressources processeur utilisées pour une requête particulière. Si vous exécutez un « travail en arrière-plan », par exemple, le système peut tolérer des latences plus élevées pour accorder une priorité élevée aux requêtes inline simultanées.

Kusto prend en charge la spécification de deux propriétés de requête lors de l’exécution d’une requête. Les propriétés sont query_fanout_threads_percent et query_fanout_nodes_percent. Les deux propriétés sont des entiers dont la valeur par défaut est la valeur maximale (100), qui peut être réduite pour une requête spécifique à une autre valeur.

La première propriété, query_fanout_threads_percent, contrôle le facteur de fanout pour l’utilisation des threads. Quand cette propriété est définie sur 100 %, le cluster affecte tous les processeurs sur chaque nœud. Par exemple, 16 UC sur un cluster déployé sur des nœuds Azure D14. Quand cette propriété est définie sur 50 %, la moitié des processeurs est utilisée, et ainsi de suite. Les nombres sont arrondis à un processeur entier.Il est donc possible de définir la valeur de propriété sur 0.

La deuxième propriété, query_fanout_nodes_percent, contrôle le nombre de nœuds de requête du cluster à utiliser par opération de distribution de sous-requête. Elle fonctionne de façon similaire.

Si query_fanout_nodes_percent ou query_fanout_threads_percent sont définis plusieurs fois, par exemple dans les propriétés de demande client et en utilisant une instruction set, la valeur inférieure pour chaque propriété est appliquée.

Limite de complexité des requêtes

Pendant l’exécution de la requête, le texte de la requête est transformé en une arborescence d’opérateurs relationnels représentant la requête. Si la profondeur de l’arborescence dépasse un seuil interne, la requête est considérée comme trop complexe pour être traitée et échoue avec un code d’erreur. L’échec indique que l’arborescence des opérateurs relationnels dépasse ses limites.

Les exemples suivants illustrent des modèles de requête courants qui peuvent entraîner le dépassement de cette limite par la requête et échouer :

  • longue liste d’opérateurs binaires chaînés ensemble. Par exemple :
T 
| where Column == "value1" or 
        Column == "value2" or 
        .... or
        Column == "valueN"

Pour ce cas spécifique, réécrivez la requête à l’aide de l’opérateur in().

T 
| where Column in ("value1", "value2".... "valueN")
  • une requête qui a un opérateur d’union qui effectue une analyse d’un schéma trop grand, en particulier quand l’implémentation par défaut de l’opérateur d’union doit retourner le schéma de l’union « externe » (c’est-à-dire que ce résultat va inclure toutes les colonnes de la table sous-jacente).

Dans ce cas, la suggestion est de passer en revue la requête et de réduire le nombre de colonnes utilisées par la requête.