你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
Kusto 查询语言 (KQL) 提供了多种查询运算符用于搜索字符串数据类型。 以下文章介绍如何为字符串词语编制索引、列出字符串查询运算符,以及提供用于优化性能的提示。
了解字符串词语
Kusto 将为所有列(包括 string 类型的列)编制索引。 将根据实际数据为这些列构建多个索引。 这些索引不会直接公开,而是在查询中使用,此类查询的 string 运算符在其名称中包含 has(如 has、!has、hasprefix、!hasprefix)。 这些运算符的语义由列的编码方式决定。 这些运算符对词语进行匹配,而不是执行“纯”子字符串匹配。
什么是词语?
默认情况下,每个 string 值都分解为字母数字字符的最大序列,并将这些序列中的每一个都转换为一个词语。
例如,在下面的 string 中,词语是 Kusto、KustoExplorerQueryRun 以及以下子字符串:ad67d136、c1db、4f9f、88ef、d94f3b6b0b5a。
Kusto: ad67d136-c1db-4f9f-88ef-d94f3b6b0b5a;KustoExplorerQueryRun
Kusto 会生成一个词语索引,该词语索引中包含的所有词语均为三个或以上字符,并且由 、has 之类的字符串运算符使用。 如果查询查找少于三个字符的词语,或者使用 contains 运算符,则该查询将恢复为扫描列中的值。 扫描的速度要比在词语索引中查找词语慢得多。
虽然 Explorer 是 KustoExplorerQueryRun的子字符串,但 "KustoExplorerQueryRun" has "Explorer" 将返回 false,而 "KustoExplorerQueryRun" contains "Explorer" 将返回 true。 这是微妙的,但行为是由于 has 基于术语的事实。
针对字符串的运算符
本文中使用了以下缩写词:
- RHS = 表达式的右侧
- LHS = 表达式的左侧
带有 _cs 后缀的运算符要区分大小写。
| 运算符 | 描述 | 区分大小写 | 示例(生成 true) |
|---|---|---|---|
== |
等于 | 是 | "aBc" == "aBc" |
!= |
不等于 | 是 | "abc" != "ABC" |
=~ |
等于 | 否 | "abc" =~ "ABC" |
!~ |
不等于 | 否 | "aBc" !~ "xyz" |
contains |
RHS 以 LHS 子序列的形式存在 | 否 | "FabriKam" contains "BRik" |
!contains |
LHS 中未出现 RHS | 否 | "Fabrikam" !contains "xyz" |
contains_cs |
RHS 以 LHS 子序列的形式存在 | 是 | "FabriKam" contains_cs "Kam" |
!contains_cs |
LHS 中未出现 RHS | 是 | "Fabrikam" !contains_cs "Kam" |
endswith |
RHS 是 LHS 的闭合子序列 | 否 | "Fabrikam" endswith "Kam" |
!endswith |
RHS 不是 LHS 的闭合子序列 | 否 | "Fabrikam" !endswith "brik" |
endswith_cs |
RHS 是 LHS 的闭合子序列 | 是 | "Fabrikam" endswith_cs "kam" |
!endswith_cs |
RHS 不是 LHS 的闭合子序列 | 是 | "Fabrikam" !endswith_cs "brik" |
has |
右侧 (RHS) 是左侧 (LHS) 的整体 | 否 | "North America" has "america" |
!has |
RHS 不是 LHS 中的完整词语 | 否 | "North America" !has "amer" |
has_all |
与 has 相同,但适用于所有元素 |
否 | "North and South America" has_all("south", "north") |
has_any |
与 has 相同,但适用于任何元素 |
否 | "North America" has_any("south", "north") |
has_cs |
RHS 是 LHS 中的完整词语 | 是 | "North America" has_cs "America" |
!has_cs |
RHS 不是 LHS 中的完整词语 | 是 | "North America" !has_cs "amer" |
hasprefix |
RHS 是 LHS 中的词语前缀 | 否 | "North America" hasprefix "ame" |
!hasprefix |
RHS 不是 LHS 中的词语前缀 | 否 | "North America" !hasprefix "mer" |
hasprefix_cs |
RHS 是 LHS 中的词语前缀 | 是 | "North America" hasprefix_cs "Ame" |
!hasprefix_cs |
RHS 不是 LHS 中的词语前缀 | 是 | "North America" !hasprefix_cs "CA" |
hassuffix |
RHS 是 LHS 中的词语后缀 | 否 | "North America" hassuffix "ica" |
!hassuffix |
RHS 不是 LHS 中的词语后缀 | 否 | "North America" !hassuffix "americ" |
hassuffix_cs |
RHS 是 LHS 中的词语后缀 | 是 | "North America" hassuffix_cs "ica" |
!hassuffix_cs |
RHS 不是 LHS 中的词语后缀 | 是 | "North America" !hassuffix_cs "icA" |
in |
等于任何元素 | 是 | "abc" in ("123", "345", "abc") |
!in |
不等于任何元素 | 是 | "bca" !in ("123", "345", "abc") |
in~ |
等于任何元素 | 否 | "Abc" in~ ("123", "345", "abc") |
!in~ |
不等于任何元素 | 否 | "bCa" !in~ ("123", "345", "ABC") |
matches regex |
LHS 包含 RHS 的匹配项 | 是 | "Fabrikam" matches regex "b.*k" |
startswith |
RHS 是 LHS 的初始子序列 | 否 | "Fabrikam" startswith "fab" |
!startswith |
RHS 不是 LHS 的初始子序列 | 否 | "Fabrikam" !startswith "kam" |
startswith_cs |
RHS 是 LHS 的初始子序列 | 是 | "Fabrikam" startswith_cs "Fab" |
!startswith_cs |
RHS 不是 LHS 的初始子序列 | 是 | "Fabrikam" !startswith_cs "fab" |
性能提示
为了获得更好的性能,当存在两个执行相同任务的运算符时,请使用区分大小写的那个运算符。 例如:
- 使用
==,而不是=~ - 使用
in,而不是in~ - 使用
hassuffix_cs,而不是hassuffix
为了更快地得到结果,如果要测试是否存在符号或字母数字式字词(受非字母数字字符或字段的开头或结尾限制),请使用 has 或 in。
has 执行起来比 contains、startswith 或 endswith 更快。
若要搜索 IPv4 地址或其前缀,请对 IPv4 地址使用某个特殊运算符,这些运算符已针对此目的进行了优化。
有关详细信息,请参阅查询最佳做法。
例如,下面的第一个查询运行速度更快:
StormEvents | where State has "North" | count;
StormEvents | where State contains "nor" | count
IPv4 地址的运算符
下面这组运算符提供针对 IPv4 地址或其前缀的索引加速搜索。
| 运算符 | 描述 | 示例(生成 true) |
|---|---|---|
| has_ipv4 | LHS 包含由 RHS 表示的 IPv4 地址 | has_ipv4("Source address is 10.1.2.3:1234", "10.1.2.3") |
| has_ipv4_prefix | LHS 包含与 RHS 表示的前缀相匹配的 IPv4 地址 | has_ipv4_prefix("Source address is 10.1.2.3:1234", "10.1.2.") |
| has_any_ipv4 | LHS 包含由 RHS 提供的 IPv4 地址之一 | has_any_ipv4("Source address is 10.1.2.3:1234", dynamic(["10.1.2.3", "127.0.0.1"])) |
| has_any_ipv4_prefix | LHS 包含与 RHS 提供的前缀之一相匹配的 IPv4 地址 | has_any_ipv4_prefix("Source address is 10.1.2.3:1234", dynamic(["10.1.2.", "127.0.0."])) |