你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
适用于 Kusto 查询语言查询的最佳做法
适用于:✅Microsoft Fabric✅Azure 数据资源管理器Azure Monitor✅Microsoft✅ 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 keys summarize ,请使用 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 包含此类列的有效索引,通常完全消除整个数据分片,而无需访问这些分片。然后应用作用于
string
和dynamic
列的谓词,尤其是在字词级别应用的谓词。 按选择性对谓词进行排序。 例如,当有数百万用户具有高度选择性时搜索用户 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
) 。
最佳做法是避免在名称限定冗余时使用名称限定,原因如下:
未限定的名称更容易识别(对于人类读者来说)为属于范围内的数据库。
引用作用域内数据库实体至少和引用属于其他数据库的实体一样快,在某些情况下甚至更快。
当这些数据库位于不同的群集中时,尤其如此。
当这些数据库位于不同的 Eventhouse 中时,尤其如此。
避免使用限定名称有助于读取者执行正确的操作。
注意
这并不意味着限定名称对性能不好。 事实上,在大多数情况下,Kusto 能够识别完全限定名称何时引用属于数据库范围内的实体并“短路”查询,以便它不被视为跨群集查询。 但是,如果不必要,我们不建议依赖此功能。
注意
这并不意味着限定名称对性能不好。 事实上,在大多数情况下,Kusto 能够识别完全限定名称何时引用属于数据库范围内的实体。 但是,如果不必要,我们不建议依赖此功能。