你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

适用于 Kusto 查询语言查询的最佳做法

适用于:✅Microsoft Fabric✅Azure 数据资源管理器Azure MonitorMicrosoft✅ Sentinel

下面是提高查询运行速度的几个最佳做法。

摘要

操作 用途 不要使用 注释
减少查询的数据量 使用 where 运算符等机制减少要处理的数据量。 有关减少正在处理的数据量的高效方法的详细信息,请参阅 减少正在处理的数据量。
避免使用冗余限定引用 引用本地实体时,请使用非限定名称。 有关详细信息,请参阅 避免使用冗余限定引用
datetime 使用 datetime 数据类型。 请勿使用 long 数据类型。 在查询中,请勿使用 Unix 时间转换函数,例如 unixtime_milliseconds_todatetime()。 而是使用更新策略在引入期间将 Unix 时间转换为 datetime 数据类型。
字符串运算符 使用 has 运算符。 不要使用 contains 查找完整标记时,has 效果更好,因为它不会查找子字符串。
区分大小写的运算符 使用 == 不使用 =~ 如果可能,请使用区分大小写的运算符。
使用 in 不使用 in~
使用 contains_cs 不使用 contains 使用has/has_cs是首选 。contains/contains_cs
搜索文本 查找特定列。 不使用 * * 对所有列执行全文搜索。
从数百万行的动态对象中提取字段 如果大多数查询从数百万行的动态对象中提取字段,则会在引入时具体化列。 使用此方法,只需为列提取付费一次。
查找动态对象中不常见的键/值 使用 MyTable | where DynamicColumn has "Rare value" | where DynamicColumn.SomeKey == "Rare value" 不使用 MyTable | where DynamicColumn.SomeKey == "Rare value" 使用此方法可以筛选掉大多数记录,并且只对其余记录执行 JSON 分析。
具有多次使用的值的 let 语句 使用 materialize() 函数 有关如何使用 materialize() 的详细信息,请参阅 materialize()。 有关详细信息,请参阅优化使用命名表达式的查询
对超过 10 亿条记录应用类型转换 调整查询以减少馈送到转换中的数据量。 如果可以避免,请勿转换大量数据。
新查询 在末尾使用 limit [small number]count 对未知数据集运行未绑定的查询可能会返回千兆字节的结果,从而导致响应缓慢和繁忙环境。
不区分大小写的比较 使用 Col =~ "lowercasestring" 不使用 tolower(Col) == "lowercasestring"
比较已小写(或大写)的数据 Col == "lowercasestring"(或 Col == "UPPERCASESTRING")。 避免使用不区分大小写的比较。
按列筛选 按表列筛选。 不要按计算列进行筛选。
使用 T | where predicate(*Expression*) 不要使用 T | extend _value = *Expression* | where predicate(_value)
summarize 运算符 当运算符具有高基数时group by keyssummarize,请使用 hint.shufflekey=<key> 理想情况下,高基数超过 100 万。
join 运算符 选择包含最少行的表作为第一行(查询中最左侧)。
使用 in 而不是 left semi join 按单个列进行筛选。
跨群集加入 跨远程环境(例如群集或 Eventhouses)在联接的“右侧”上运行查询,其中大部分数据位于其中。
左侧较小且右侧较大时联接 使用 hint.strategy=broadcast 小型是指最多 100 兆字节(MB)的数据。
右侧较小且左侧较大时联接 使用 lookup 运算符而不是 join 运算符 如果查找右侧大于几十 MB,则查询将失败。
当双方太大时联接 使用 hint.shufflekey=<key> 当联接键具有高基数时使用。
提取具有相同格式或模式的字符串的列上的值 使用分析运算符 不要使用几个 extract() 语句。 例如,值,如 "Time = <time>, ResourceId = <resourceId>, Duration = <duration>, ....".
extract() 函数 当分析的字符串不都遵循相同的格式或模式时使用。 使用 REGEX 提取所需的值。
materialize() 函数 推送所有可能减少具体化数据集的运算符,但仍保留查询的语义。 例如,筛选器或仅项目所需的列。 有关详细信息,请参阅优化使用命名表达式的查询
使用具体化视图 使用具体化视图存储常用聚合。 首选使用 materialized_view() 函数仅查询具体化部件。 materialized_view('MV')

减少要处理的数据量

查询性能直接取决于它需要处理的数据量。 处理的数据越少,查询速度越快(并且消耗的资源越少)。 因此,最重要的最佳做法是以减少要处理的数据量的方式构建查询。

注意

在以下讨论中,必须牢记筛选器选择性的概念。 选择性是指当按某个谓词进行筛选时,记录被筛选出的百分比。 高选择性谓词是指应用该谓词后仅保留少量记录,从而减少需要有效处理的数据量。

按重要性排序:

  • 仅引用查询需要其数据的表。 例如,将 union 运算符与通配符表引用结合使用时,最好从性能点到仅引用少数表,而不是使用通配符(*)引用所有表,然后使用源表名称上的谓词筛选出数据。

  • 如果查询仅与特定范围相关,请利用表的数据范围。 table() 函数提供了一种有效方式用于根据缓存策略(DataScope 参数)确定数据范围来消除数据。

  • 在表引用之后紧接着应用 where 查询运算符。

  • 使用 where 查询运算符时,无论使用单个 where 运算符还是多个连续 where 运算符,您放置谓词的顺序都对查询性能产生重大影响。

  • 首先应用完整分片谓词。 这意味着应首先应用使用 extent_id() 函数extent_tags() 函数 的谓词。 此外,如果你有选择性谓词,可将数据缩小到特定分区,则应首先应用它们。

  • 然后应用作用于 datetime 表列的谓词。 Kusto 包含此类列的有效索引,通常完全消除整个数据分片,而无需访问这些分片。

  • 然后应用作用于 stringdynamic 列的谓词,尤其是在字词级别应用的谓词。 按选择性对谓词进行排序。 例如,当有数百万用户具有高度选择性时搜索用户 ID,通常涉及字词搜索,索引非常有效。

  • 然后应用选择性的且基于数字列的谓词。

  • 最后,对于扫描表列数据的查询(例如,对于没有字词且不受益于索引的谓contains"@!@!"词),请对谓词进行排序,以便先扫描包含较少数据的列。 这样做可以减少解压缩和扫描大型列的需求。

避免使用冗余限定引用

按名称引用表和具体化视图等实体。

例如,可以将表 T 引用为简单 T非限定 名称),也可以使用数据库限定符(例如, database("DB").T 当表位于调用 DB的数据库时),或使用完全限定的名称(例如, cluster("<serviceURL>").database("DB").T) 。

例如,可以将表 T 引用为简单 T非限定 名称),也可以使用数据库限定符(例如, database("DB").T 当表位于调用 DB的数据库时),或使用完全限定的名称(例如, cluster("X.Y.kusto.windows.net").database("DB").T) 。

最佳做法是避免在名称限定冗余时使用名称限定,原因如下:

  1. 未限定的名称更容易识别(对于人类读者来说)为属于范围内的数据库。

  2. 引用作用域内数据库实体至少和引用属于其他数据库的实体一样快,在某些情况下甚至更快。

当这些数据库位于不同的群集中时,尤其如此。

当这些数据库位于不同的 Eventhouse 中时,尤其如此。

避免使用限定名称有助于读取者执行正确的操作。

注意

这并不意味着限定名称对性能不好。 事实上,在大多数情况下,Kusto 能够识别完全限定名称何时引用属于数据库范围内的实体并“短路”查询,以便它不被视为跨群集查询。 但是,如果不必要,我们不建议依赖此功能。

注意

这并不意味着限定名称对性能不好。 事实上,在大多数情况下,Kusto 能够识别完全限定名称何时引用属于数据库范围内的实体。 但是,如果不必要,我们不建议依赖此功能。