🛡️Master the Art of Microsoft Advanced Hunting: KQL Queries Best Practices for Uncovering Hidden Threats🛡️
Apply these recommendations to get results faster and avoid timeouts while running complex queries.
📝Action: Time filters
Use: Use time filters first
Notes: Kusto is highly optimized to use time filters.
📝Action: String operators
Use: use the has operator
Don’t use: Don’t use contains
Notes: When looking for full tokens, has works better, since it doesn’t look for substrings.
📝Action: Case-sensitive operators
Don’t use: =~
Notes: Use case-sensitive operators when possible.
📝Action: Searching text
Use: Look in a specific column
Don’t use: *
Notes: * does a full text search across all columns.
📝Action: Extract fields from dynamic objects across millions of rows
Use: Materialize your column at ingestion time if most of your queries extract fields from dynamic objects across millions of rows.
Notes: This way, you’ll only pay once for column extraction.
📝Action: New queries
Use: Use limit [small number] or count at the end.
Notes: Running unbound queries over unknown data sets may yield GBs of results to be returned to the client, resulting in a slow response and a busy cluster.
📝Action: summarize operator
Use: Use the hint.shufflekey=<key> when the group by keys of the summarize operator are with high cardinality.
Notes: High cardinality is ideally above 1 million.
📝Action: extract() function
Use: Use when parsed strings don’t all follow the same format or pattern.
Notes: Extract the required values by using a REGEX.
📝Action: materialize() function
Use: Push all possible operators that will reduce the materialized data set and still keep the semantics of the query.
Notes: For example, filters, or project only required columns
📝Action: Use materialized views
Use: Use materialized views for storing commonly used aggregations. Prefer using the materialized_view() function to query materialized part only