Important

This feature is in an experimental state. Future updates might change or remove functionality without maintaining compatibility with existing implementations.

The explain:asTable() function analyzes query performance and identifies bottlenecks or incorrect filters. explain:asTable() activates profiling mode, which collects performance statistics during event processing, including processing time, event counts, and prefilter effectiveness.

The explain:asTable() function overrides any previous query results and outputs performance data instead.

Only use the explain:asTable() function for ad hoc performance analysis. Do not include explain:asTable() in scheduled searches or triggers.

ParameterTypeRequiredDefault ValueDescription
showPrefiltersbooleanoptional[a] true Controls whether prefilter statistics are included in the output. When set to true, it includes information about prefilter effectiveness and optimization.

[a] Optional parameters use their default value unless explicitly set.

explain:asTable() Function Operation

When added to a query, the explain:asTable() function:

  • Collects performance statistics during query execution.

  • Measures processing time for each query step.

  • Tracks the number of events processed for each query step.

  • Captures timing data for join() and defineTable() subqueries.

  • Reports prefilter effectiveness statistics that arise from tag filters and substring filters.

Note

Important usage considerations:

  • Use this function only for ad hoc performance analysis.

  • Do not include in scheduled searches.

  • Do not include in triggers.

  • The function analyzes the optimized query rather than the original query.

  • The function is not supported in combination with correlate().

Output Format

The explain:asTable() function generates a table with the following columns:

Column Description
stepID Identifies each query step
step Describes the operation performed
timeMs Shows processing time in milliseconds
events Lists the number of processed input events to the given step
additionalData Contains supplementary information for specific operations

Time Measurement Details

The query plan measures processing time for each event using nanosecond-precision wallclock measurement.

LogScale executes query steps in parallel until it reaches the first aggregate function (the aggregate included). The total time represents the sum of all parallel processes. This parallel execution can make the reported time appear larger than the actual real-time duration.

Note

These factors affect time measurement accuracy:

  • Concurrent system operations affect query timing precision. Any concurrent work on the system can cause imprecision of time spent in the query.

  • System interrupts appear in query execution time. Any system interrupts to the process running the query will also show up as time spent in the query.

  • Parallel processing creates cumulative time measurements. The parallel execution nature of Logscale means that reported times are sums across processes.

Query Optimization Effects

Logscale optimizes queries before execution. This means that the query plan that is actually executed might be different from the query submitted by the user. explain:asTable() outputs the performance of the actual query that is executed, thus its output might contain steps which are different from the query submitted by the user.

Query optimization might create these typical differences:

  • Tag filters become prefilters. For example, #kind=logs moves to the prefilter section. Prefilters select data sources from storage and appear in the prefilter output section of explain:asTable().

  • Field existence checks appear as new steps. For example, x = 42 creates an x = * filter at the query start.

  • Steps execute in optimized order. The query optimizer places the most efficient filters first.

For example, consider this query:

logscale
#kind=logs
| rename(x, as=y)
| category="ScheduledSearch"

When profiling this query with explain:asTable(), the output shows:

stepIDsteptimeMseventsadditionalData
<no value>prefilters<no value><no value>bytes searched: 47,494,832, bytes skipped: 141,462,104, skip rate: 74
1category = *17115680<no value>
2category = "ScheduledSearch"13604<no value>
3rename(x, as=y)0772<no value>

explain:asTable() Syntax Examples

Profile a simple filtering and counting operation to understand the performance characteristics of the explain:asTable() function.

This example demonstrates basic query profiling with prefilter statistics disabled (showPrefilters parameter set to false).

logscale
x = 42 
| count()
| explain:asTable(showPrefilters=false)

If input data contains x=42, x=42, x=41, it would return:

stepIDsteptimeMsevents
1x = *03
2x = "42"13
3count()12

Note that the profiled query plan gets an additional step that was not present in the original query, namely the x = * part. This is because the profiling mode runs on the optimized query plan, which in this case got an extra field existence check for improved filtering performance.

This example shows profiling a query with defineTable()

logscale
defineTable(
    query={sort(name, order=ascending)},
    include=[userid, name, role],
    name="users"
  )
| match(users, field=["user_id"], column=userid)
| explain:asTable()

If input data was:

useridnameroleuser_id
user1Aliceadmin<no value>
user2Bobuser<no value>
user1Alice Updatedsuperadmin<no value>
<no value><no value><no value>user1
<no value><no value><no value>user3

It would return:

stepIDsteptimeMseventsadditionalData
<no value>table: users500<no value><no value>
<no value>prefilters<no value><no value>bytes_searched: 320, bytes skipped: 0, skip rate: 0
1match(users, field=["user_id"], column=userid)105<no value>

This example shows profiling a query with a join operation.

logscale
join(field=x,query={x=42})
| count()
| explain:asTable(showPrefilters=false)

With input data x=42, x=42, x=40, it produces:

stepIDsteptimeMsevents
<no value>join subquery at stepID=2480<no value>
1x = *03
2join(field=x,query={x=42})03
3count()12

Click + next to an example below to get the full details.

Profile Performance of Join Operations

Analyze query performance of join operations with filtering using the explain:asTable() function with join()

Query
logscale
join(field=x, query={x=42})
| count()
| explain:asTable(showPrefilters=false)
Introduction

In this example, the explain:asTable() function is used to profile a query that performs a join operation with a filter condition.

Example incoming data might look like this:

@timestampxvalue
2025-11-05T10:00:00Z42100
2025-11-05T10:00:01Z42200
2025-11-05T10:00:02Z41300
2025-11-05T10:00:03Z42400
2025-11-05T10:00:04Z43500
Step-by-Step
  1. Starting with the source repository events.

  2. logscale
    join(field=x, query={x=42})

    Performs a join operation on the field x, matching only events where x equals 42. The field parameter specifies which field to join on, while the query parameter filters the events to include in the join.

  3. logscale
    | count()

    Counts the number of events resulting from the join operation.

  4. logscale
    | explain:asTable(showPrefilters=false)

    Generates a performance profile of the query execution, with the showPrefilters parameter set to false to exclude prefilter statistics from the output.

  5. Event Result set.

Summary and Results

The query is used to analyze the performance characteristics of a filtered join operation followed by an aggregation.

This query is useful, for example, to understand the performance impact of join operations and their associated filters, helping to optimize queries that require correlating events based on field values.

Sample output from the incoming example data:

stepIDsteptimeMsevents 
<no value>join subquery at stepID=210<no value> 
1x = *51 
2join(field=x, query={x=42})52 
"3","count()","3",1"    

Note that the output shows three distinct steps: the join operation itself, the filter condition, and the final count. The events column shows how many events are processed at each step, with the join operation processing all events, the filter reducing to matching events, and the count producing a single result.

The execution time (timeMs field) for each step helps identify which parts of the query are most resource-intensive.

Profile Performance of Lookup Operations

Analyze query performance when using the explain:asTable() with defineTable() and match() for data enrichment

Query
logscale
| defineTable(query={sort(name, order=ascending)}, include=[userid, name, role], name="users")
| match(users, field=["user_id"], column=userid)
| explain:asTable()
Introduction

In this example, the explain:asTable() function is used to profile a query that creates a lookup table and performs data enrichment using match().

Example incoming data might look like this:

@timestampuser_idactionresource
2025-11-05T10:00:00ZU123loginapp1
2025-11-05T10:00:01ZU456logoutapp2
2025-11-05T10:00:02ZU789accessapp1
2025-11-05T10:00:03ZU123logoutapp2

And the user reference data (used in the lookup table) might look like this:

@timestampuseridnamerole
2025-11-05T10:00:00ZU123John Smithadmin
2025-11-05T10:00:00ZU456Jane Doeuser
2025-11-05T10:00:00ZU789Bob Wilsonuser
Step-by-Step
  1. Starting with the source repository events.

  2. logscale
    | defineTable(query={sort(name, order=ascending)}, include=[userid, name, role], name="users")

    Creates a lookup table named users containing user reference data, sorted in ascending order by the name field. The table includes only the fields specified in the include parameter: userid, name, and role.

  3. logscale
    | match(users, field=["user_id"], column=userid)

    Performs a lookup operation that enriches the main event stream with data from the users lookup table. The lookup matches the user_id field from the main events with the userid column from the lookup table, adding the corresponding name and role fields to matching events.

  4. logscale
    | explain:asTable()

    Generates a performance profile of the entire query execution, including the table definition and lookup operations. Uses default settings to show all execution steps, including prefilters.

  5. Event Result set.

Summary and Results

The query is used to analyze the performance characteristics of table creation and lookup operations in LogScale.

This query is useful to understand the performance impact of subqueries as well as lookup table operations.

Sample output from the incoming example data:

stepIDstepadditionalDataeventstimeMs
<no value>table: users<no value><no value>200
"","prefilters","bytes searched: 49,834    
bytes skipped: 0    
skip rate: 0","",""    
1match(users, field=["user_id"], column=userid)<no value>14

Note that the output shows the execution time for each major operation: table definition, sorting, and matching. The prefilter steps indicate how many events were initially considered before the main operations began.

The match step shows the total number of events that were successfully enriched with data from the lookup table, while the table definition steps show the number of events processed for creating the lookup table.

Profile Query Performance

Analyze query execution steps and their performance metrics using the explain:asTable() function

Query
logscale
x = 42
| count()
| explain:asTable(showPrefilters=false)
Introduction

In this example, the explain:asTable() function is used to profile a simple filtering and counting operation with prefilter statistics disabled.

Example incoming data might look like this:

@timestampx
2025-11-05T10:00:00Z42
2025-11-05T10:00:01Z42
2025-11-05T10:00:02Z41
Step-by-Step
  1. Starting with the source repository events.

  2. logscale
    x = 42

    Filters events where the field x equals 42.

  3. logscale
    | count()

    Counts the number of events that match the filter condition.

  4. logscale
    | explain:asTable(showPrefilters=false)

    Generates a performance profile of the query execution, with the showPrefilters parameter set to false to exclude prefilter statistics from the output.

  5. Event Result set.

Summary and Results

The query is used to analyze the performance characteristics of a simple filtering and counting operation.

This query is useful, for example, to identify potential performance bottlenecks in queries, how events are filtered through steps, and to understand how the query is optimized.

Sample output from the incoming example data:

stepIDsteptimeMsevents
1x = *03
2x = "42"13
3count()12

Note that the profiled query plan includes an additional step (x = *) that was not present in the original query. This is because the profiling mode runs on the optimized query plan, which in this case added an extra field existence check for improved filtering performance.