Passer au contenu principal

Recherche dans ClickStack et Elastic

ClickHouse est un moteur nativement SQL, conçu dès le départ pour les charges de travail analytiques à hautes performances. À l’inverse, Elasticsearch propose une interface de type SQL, en transpilant le SQL vers le DSL de requête Elasticsearch sous-jacent — autrement dit, SQL n’y est pas pris en charge nativement, et la parité fonctionnelle reste limitée. ClickHouse prend non seulement en charge l’ensemble du SQL, mais l’étend également avec une série de fonctions axées sur l’observabilité, comme argMax, histogram et quantileTiming, qui simplifient les requêtes sur des logs, metrics et traces structurés. Pour explorer simplement les logs et les traces, la ClickStack UI (HyperDX) fournit une syntaxe de type Lucene permettant un filtrage textuel intuitif sur des requêtes champ-valeur, des plages, des caractères génériques, etc. Cela est comparable à la syntaxe Lucene dans Elasticsearch, ainsi qu’à certains éléments du Kibana Query Language. L’interface de recherche prend en charge cette syntaxe familière, mais la traduit en arrière-plan en clauses SQL WHERE efficaces. L’expérience reste ainsi familière pour les utilisateurs de Kibana, tout en leur permettant d’exploiter, si nécessaire, toute la puissance du SQL. Vous pouvez ainsi tirer parti de toute la gamme des string search functions, des similarity functions et des fonctions de date et heure dans ClickHouse. Ci-dessous, nous comparons les langages de requête Lucene de ClickStack et d’Elasticsearch.

Syntaxe de recherche ClickStack vs query string Elasticsearch

ClickStack et Elasticsearch offrent tous deux des langages de requête flexibles pour permettre un filtrage intuitif des logs et des traces. Alors que le query string d’Elasticsearch est étroitement intégré à son DSL et à son moteur d’indexation, ClickStack prend en charge une syntaxe inspirée de Lucene, traduite en ClickHouse SQL en arrière-plan. Le tableau ci-dessous montre le comportement des modèles de recherche courants dans les deux systèmes, en soulignant les similitudes de syntaxe et les différences d’exécution côté backend.
FonctionnalitéSyntaxe ClickStackSyntaxe ElasticsearchCommentaires
Recherche en texte libreerrorerrorCorrespond à tous les champs indexés ; dans ClickStack, cela est réécrit en SQL ILIKE sur plusieurs champs.
Correspondance de champlevel:errorlevel:errorSyntaxe identique. ClickStack fait correspondre les valeurs exactes des champs dans ClickHouse.
Recherche d’expression"disk full""disk full"Le texte entre guillemets correspond à une séquence exacte ; ClickHouse utilise l’égalité de chaînes ou ILIKE.
Correspondance d’expression sur un champmessage:"disk full"message:"disk full"Se traduit en SQL ILIKE ou en correspondance exacte.
Conditions ORerror OR warningerror OR warningOR logique entre les termes ; les deux systèmes le prennent en charge nativement.
Conditions ANDerror AND dberror AND dbLes deux se traduisent par une intersection ; aucune différence dans la syntaxe utilisateur.
NégationNOT error ou -errorNOT error ou -errorPris en charge de façon identique ; ClickStack convertit cela en SQL NOT ILIKE.
Groupement(error OR fail) AND db(error OR fail) AND dbGroupement booléen standard dans les deux cas.
Caractères génériqueserror* ou *fail*error*, *fail*ClickStack prend en charge les caractères génériques en début et en fin ; ES désactive par défaut ceux en début de terme pour des raisons de performances. Les caractères génériques au sein d’un terme ne sont pas pris en charge, par ex. f*ail. Les caractères génériques doivent être appliqués avec une correspondance de champ.
Plages (numériques/date)duration:[100 TO 200]duration:[100 TO 200]ClickStack utilise SQL BETWEEN ; Elasticsearch l’étend en requêtes de plage. Les * non bornés dans les plages ne sont pas pris en charge, par ex. duration:[100 TO *]. Si nécessaire, utilisez Unbounded ranges ci-dessous.
Plages non bornées (numériques/date)duration:>10 ou duration:>=10duration:>10 ou duration:>=10ClickStack utilise les opérateurs SQL standard
Inclusif/exclusifduration:{100 TO 200} (exclusive)Same{} indique des bornes exclusives. Les * dans les plages ne sont pas pris en charge, par ex. duration:[100 TO *]
Vérification d’existenceN/A_exists_:user ou field:*_exists_ n’est pas pris en charge. Utilisez LogAttributes.log.file.path: * pour les colonnes Map, par ex. LogAttributes. Pour les colonnes racine, elles doivent exister et auront une default value si elles ne sont pas incluses dans l’événement. Pour rechercher des default values ou des colonnes manquantes, utilisez la même syntaxe qu’Elasticsearch : ServiceName:* ou ServiceName != ''.
Regexmatch functionname:/joh?n(ath[oa]n)/Actuellement non pris en charge dans la syntaxe Lucene. Vous pouvez utiliser SQL et la fonction match ou d’autres string search functions.
Correspondance approximativeeditDistance('quikc', field) = 1quikc~Actuellement non pris en charge dans la syntaxe Lucene. Les Distance functions peuvent être utilisées en SQL, par ex. editDistance('rror', SeverityText) = 1 ou other similarity functions.
Recherche de proximitéNot supported"fox quick"~5Actuellement non pris en charge dans la syntaxe Lucene.
Pondérationquick^2 foxquick^2 foxNon pris en charge dans ClickStack à l’heure actuelle.
Caractère générique de champservice.*:errorservice.*:errorNon pris en charge dans ClickStack à l’heure actuelle.
Caractères spéciaux échappésEscape reserved characters with \SameL’échappement est requis pour les symboles réservés.

Différences entre existence et valeur manquante

Contrairement à Elasticsearch, où un champ peut être entièrement omis d’un événement et donc réellement « ne pas exister », ClickHouse exige que toutes les colonnes d’un schéma de table soient présentes. Si un champ n’est pas fourni dans un événement d’insertion :
  • Pour les champs Nullable, il sera défini sur NULL.
  • Pour les champs non nullables (par défaut), il recevra une valeur par défaut (souvent une chaîne vide, 0 ou une valeur équivalente).
Dans ClickStack, nous utilisons ce second cas, car Nullable est déconseillé. Cela signifie qu’il n’est pas possible de vérifier directement si un champ « existe » au sens d’Elasticsearch. À la place, vous pouvez utiliser field:* ou field != '' pour vérifier la présence d’une valeur non vide. Il n’est donc pas possible de distinguer un champ réellement manquant d’un champ explicitement vide. En pratique, cette différence pose rarement problème pour les cas d’usage d’observabilité, mais il est important de la garder à l’esprit lors de la traduction de requêtes d’un système à l’autre.
Dernière modification le 29 juin 2026