KQL 中的“has”和“contains”运算符有什么区别?

man*_*ore 7 azure kql

hasKQL 中的和运算符有什么区别contains

has操作员文档。是操作员的文档contains

它们都检查是否存在不区分大小写的字符串。那么,这是否意味着使用一个运算符而不是另一个运算符只是一种品味问题?

Dav*_*itz 14

  • 如果搜索的字符串存在于搜索的文本中,包含将始终返回 true。
  • 结果取决于搜索文本中搜索字符串的周围。

为什么在某些情况下我们应该更喜欢has而不是contains
TL;DR:性能(使用索引与数据扫描)。


术语是字母数字字符的序列(请参阅什么是术语?)。

一些例子:

  • 1Hello2WorldZ42都是术语。
  • Hello-WorldHello_WorldHello World均由 2 个术语构成。
  • 056c8e97-422f-4e29-836b-ec3b0d77a50b(GUID 的示例)由 5 个术语构成。
  • !@#$%^&*()没有条件

Azure 数据资源管理器(AKA ADX、AKA Kusto)对每个术语进行索引,只要其长度为 3 个字符或更多(对于存储引擎 v3。对于 v2,它是 4 个字符)。
索引(全文搜索索引)使 ADX 能够在亚秒/秒内返回搜索结果,即使搜索是在 PB 上完成的。
截至今天,该索引可用于整个术语搜索或前缀搜索。

以下是contains & has对于不同搜索字符串的行为:

  • 埃尔
    • contains在ellHellEllaHELLO7ell8 & (.ell.)等文本中查找搜索的字符串,产生数据扫描(不使用索引)。
    • 利用索引在ellEllELL、 & (.ell.)等文本中查找搜索到的字符串。如果搜索的字符串包含在较长的术语中(例如, bellEllaHello) ,
      则 has找不到该字符串
  • 埃尔
    • 与上面的示例类似,但这两个运算符都不使用索引,因为索引仅包含 3 个或更多字符的术语。
  • #呃#
    • 两个运算符返回相同的结果。
    • 两个运算符都利用索引(整个术语搜索)对术语 ( ell ) 进行初始过滤,然后进行缩小数据扫描(以过滤整个搜索字符串)。
  • #ell
    • contains查找文本中搜索的字符串,例如#ell@#Ell#@#Ella等。
    • 在#ell & @#Ell#@等文本中查找搜索到的字符串。如果术语 ( ell ) 是较长术语(例如Ella )的前缀,
      则 has找不到搜索的字符串。
    • 两个运算符都利用索引(has执行整个术语搜索,而contains执行前缀搜索)对术语 ( ell ) 进行初始过滤,然后进行缩小数据扫描(以过滤整个搜索字符串)。
    • 在这种情况下,hasprefix 的行为与 *contains 完全相同。
  • 呃#
    • contains查找文本中搜索的字符串,例如ell#@#Ell#@Hell#等。
    • 在ell# & @#Ell#@等文本中查找搜索到的字符串如果术语 ( ell ) 是较长术语(例如Cell )的后缀,
      则 has找不到搜索的字符串。对指数有杠杆作用,而contains则没有。
    • 在这种情况下,hassuffix 的行为与 *contains 完全相同。

PS 即使一个术语被索引,也可能不会使用索引,例如,当一个术语非常常见时,直接扫描数据本身可能比使用索引更便宜。

以下是通过contains而不是has找到的搜索字符串的一些示例。
请注意以下事项:

  • contains总是找到搜索到的子字符串 (hellhello)。
  • 从未找到子字符串hell
  • hello只要它不是较长字母数字序列的一部分,就会找到所搜索的子字符串。
datatable(txt:string)
[
    "Hello World"
   ,"<Hello-World>"
   ,"*Hello*World*"
   ,"?Hello%World!"
   ,"_Hello_World_"
   ,"123Hello-World456"
   ,"abcHello Worldxyz"
   ,"HelloWorld"
]
| extend contains_hell  = txt contains  "hell"
        ,contains_hello = txt contains  "hello"
        ,has_hell       = txt has       "hell"
        ,has_hello      = txt has       "hello"
Run Code Online (Sandbox Code Playgroud)
TXT 包含地狱 包含_hello 有地狱 有_你好
你好世界 真的 真的 错误的 真的
<你好世界> 真的 真的 错误的 真的
*你好世界* 真的 真的 错误的 真的
?你好世界! 真的 真的 错误的 真的
你好世界 真的 真的 错误的 真的
123Hello-World456 真的 真的 错误的 错误的
abcHello Worldxyz 真的 真的 错误的 错误的
你好世界 真的 真的 错误的 错误的

小提琴