Back to Redis

FT.PROFILE

content/commands/ft.profile.md

latest21.0 KB
Original Source

Apply [FT.SEARCH]({{< relref "commands/ft.search/" >}}) or [FT.AGGREGATE]({{< relref "commands/ft.aggregate/" >}}) command to collect performance details. For usage, see Examples.

Required arguments

<details open> <summary><code>index</code></summary>

is the name of an index created using [FT.CREATE]({{< relref "commands/ft.create/" >}}).

</details> <details open> <summary><code>SEARCH | AGGREGATE</code></summary>

represents the profile type, either [FT.SEARCH]({{< relref "commands/ft.search/" >}}) or [FT.AGGREGATE]({{< relref "commands/ft.aggregate/" >}}).

</details> <details open> <summary><code>LIMITED</code></summary>

removes details of any reader iterators.

</details> <details open> <summary><code>QUERY {query}</code></summary>

is the query string, sent to FT.SEARCH or FT.AGGREGATE.

</details>

<note><b>Note:</b> To reduce the size of the output, use NOCONTENT or LIMIT 0 0 to reduce the number of reply results, or LIMITED to not reply with details of reader iterators inside built-in unions, such as fuzzy or prefix iterators.</note>

Return

{{< note>}} This page contains the up-to-date profile output as of RediSearch v2.8.33, v2.10.26, v8.2.7, and v8.4.3. The output format itself may differ between RediSearch versions, and RESP protocol versions. {{< /note >}}

FT.PROFILE returns a two-element array reply. The first element contains the results of the provided FT.SEARCH or FT.AGGREGATE command. The second element contains information about query creation, iterator profiles, and result processor profiles. Details of the second element follow in the sections below.

Per-shard profiles

This section contains query execution details for each shard. When more than one shard is in play, the shards will be labeled Shard #1, Shard #2, etc. If there's only one shard, the label will be omitted.

Returned field nameDefinition
Shard IDString containing the unique shard ID. In Redis Open Source, this identifier is denoted as the node ID, and is received from the RedisModule_GetMyClusterID() API. (Available as of RediSearch v8.4.3)
Total profile timeThe total run time (ms) of the query. Normally just a few ms.
Parsing timeThe time (ms) spent parsing the query and its parameters into a query plan. Normally just a few ms.
Pipeline creation timeThe creation time (ms) of the execution plan, including iterators, result processors, and reducers creation. Normally just a few ms for FT.SEARCH queries, but expect a larger number for FT.AGGREGATE queries.
Total GIL timeIn multi-threaded deployments, the total time (ms) the query spent holding and waiting for the Redis Global Lock (referred to as GIL) during execution. Note: this value is only valid in the shards profile section.
WarningErrors that occurred during query execution.
Internal cursor readsThe number of times the coordinator fetched result batches from a given shard during a distributed AGGREGATE query in cluster mode. Includes the initial request plus any subsequent batch fetches.

Iterator profiles

This section contains index iterator information, including Type, Query Type, Term (when applicable), Time (ms), Number of reading operations, Child iterator, and Estimated number of matches information. Each iterator represents an executor for each part of the query plan, nested per the execution plan. The operation types mentioned below (for example, UNION) should match up with the provided query.

Inverted-index iterators also include the number of elements they contain. Vector iterators include additional profiling information. See Notes on Vector iterator profile below.

Iterator types include:

  • INTERSECT (and) with Child iterator
  • UNION (or) with Child iterator
  • NOT (-) with Child iterator
  • Child iterator - details of a sub-query component of a compound query.
  • TEXT with Term
  • TAG with Term
  • NUMERIC with Term
  • VECTOR
  • METRIC - VECTOR DISTANCE
  • GEO with Term
  • EMPTY
  • WILDCARD
  • OPTIONAL
  • OPTIMIZER with Optimizer mode - Query optimization wrapper for FT.SEARCH queries sorted by a numeric field. Enabled by default in [DIALECT 4]({{< relref "/develop/ai/search-and-query/advanced-concepts/dialects##dialect-4-deprecated" >}}) or explicitly with WITHOUTCOUNT.
  • ID-LIST - Iterator over specific document IDs (appears when using INKEYS)

Notes on Number of reading operations and Estimated number of matches

Number of reading operations is the number of times an iterator was interacted with. A very high value in comparison to others is a possible warning flag. NUMERIC and Child iterator types are broken into ranges, and Number of reading operations will vary depending on the range. For UNION, the sum of the reading operations in child iterators should be equal to or greater than the child iterator's reading operations.

Estimated number of matches is the size of the document set. Number of reading operations should always be equal to or less than Estimated number of matches.

Notes on Vector iterator profile {#notes-onvector-iterator-profile}

For vector queries, the iterator profile includes additional information specific to vector search execution.

Vector search mode

The Vector search mode field indicates the execution strategy used for both VECTOR and METRIC - VECTOR DISTANCE iterator types:

ModeDescription
STANDARD_KNNPure KNN vector search without filters.
RANGE_QUERYRange-based vector search. Used with VECTOR_RANGE queries.
HYBRID_ADHOC_BFAd-hoc brute force for filtered queries. Iterates through results that pass the filter and calculates distances on-the-fly.
HYBRID_BATCHESBatch-based filtered search. Retrieves top vectors from the index in batches and checks which ones pass the filter.
HYBRID_BATCHES_TO_ADHOC_BFDynamic mode switching. Starts with batch-based search but switches to ad-hoc brute force if batch iterations yield insufficient results.

Batch execution statistics

For queries using batch modes (HYBRID_BATCHES or HYBRID_BATCHES_TO_ADHOC_BF), additional batch statistics are included:

Returned field nameDefinition
Batches numberTotal number of batch iterations executed during the search.
Largest batch sizeThe maximum batch size used during execution. Batch sizes may vary dynamically based on the ratio of estimated matching documents to total index size.
Largest batch iteration (zero based)The iteration number (0-based) when the largest batch occurred.

Result processor profiles

Result processors form a powerful pipeline in Redis Search. They work in stages to gather, filter, score, sort, and return results as efficiently as possible based on complex query needs. Each processor reports Time information, which represents the total duration (in milliseconds, or ms) spent by the processor to complete its operation, and Results processed information, which indicates the number of times the processor was invoked during the query.

TypeDefinition
Metrics ApplierThe Metrics Applier processor calculates or aggregates specific metrics related to the search results. For example, this might include applying a distance or similarity metric to vector search results, or calculating scores based on relevance or other parameters.
IndexThe Index processor is responsible for the core retrieval of matching documents from the index based on the initial query criteria (e.g., full-text terms, filters, or numeric ranges).
ScorerThe Scorer processor assigns a relevance score to each document based on the query’s specified scoring function. This function could involve factors like term frequency, inverse document frequency, or other weighted metrics.
SorterThe Sorter processor arranges the query results based on a specified sorting criterion. This could be a field value (e.g., sorting by price, date, or another attribute) or by the score assigned during the scoring phase. It operates after documents are fetched and scored, ensuring the results are ordered as required by the query (e.g., ascending or descending order). Scorer results will always be present in FT.SEARCH profiles.
LoaderThe Loader processor retrieves the document contents after the results have been sorted and filtered. It ensures that only the fields specified by the query are loaded, which improves efficiency, especially when dealing with large documents where only a few fields are needed.
Threadsafe-LoaderThe Threadsafe-Loader processor safely loads document contents when the query runs in a background thread (relevant for multi-threaded deployments). It acquires the Redis Global Lock (referred to as GIL) to access document data. Reports an additional GIL-Time field representing the time (ms) spent holding the GIL and waiting to acquire it.
HighlighterThe Highlighter processor is used to highlight matching terms in the search results. This is especially useful for full-text search applications, where relevant terms are often emphasized in the UI.
Pager/LimiterThe Pager/Limiter processor is responsible for handling pagination by limiting the results to a specific range (e.g., LIMIT 0 10).It trims down the set of results to fit the required pagination window, ensuring efficient memory usage when dealing with large result sets.
CounterThe Counter processor counts the total number of matching results. Used when running queries with LIMIT 0 0 to return only the count.
GrouperThe Grouper processor groups results by field values. Used with GROUPBY in FT.AGGREGATE queries.
ProjectorThe Projector processor applies field transformations. Used with APPLY in FT.AGGREGATE queries.
NetworkCollects and merges results from shards. Appears as the root processor in the coordinator's result processor chain for FT.AGGREGATE in cluster mode.

Coordinator

This section is only present when run in a multi-shard environment.

Returned field nameDefinition
Total coordinator timeTime measured from the beginning of query execution until all shards have completed query execution. (ms)
Post-processing timeThe time spent generating the FT.PROFILE output (overhead) (ms).

Examples

<details> <summary><b>Collect performance information about a simple JSON index.</b></summary>

Imagine you have (1) a dataset consisting of 10 JSON documents, each with the following structure;

json
{
  "pickup_zone": "POLYGON((-74.0610 40.7578, -73.9510 40.7578, -73.9510 40.6678, -74.0610 40.6678, -74.0610 40.7578))",
  "store_location": "-74.0060,40.7128",
  "brand": "Velorim",
  "model": "Jigger",
  "price": 270,
  "description": "Small and powerful, the Jigger is the best ride for the smallest of tikes! This is the tiniest kids’ pedal bike on the market available without a coaster brake, the Jigger is the vehicle of choice for the rare tenacious little rider raring to go.",
  "condition": "new"
}

And (2) a corresponding index:

bash
FT.CREATE idx:bicycle ON JSON PREFIX 1 bicycle: SCORE 1.0 SCHEMA $.pickup_zone AS pickup_zone GEOSHAPE $.store_location AS store_location GEO $.brand AS brand TEXT WEIGHT 1.0 $.model AS model TEXT WEIGHT 1.0 $.description AS description TEXT WEIGHT 1.0 $.price AS price NUMERIC $.condition AS condition TAG SEPARATOR ,

Here's an example of running the FT.PROFILE command for a compound query.

{{< highlight bash >}} 127.0.0.1:6379> ft.profile idx:bicycle search query "@description:(kids | small) @condition:{new | used}"

    1. (integer) 3
    2. "bicycle:0"
      1. "$"
      2. "{"pickup_zone":"POLYGON((-74.0610 40.7578, -73.9510 40.7578, -73.9510 40.6678, -74.0610 40.6678, -74.0610 40.7578))","store_location":"-74.0060,40.7128","brand":"Velorim","model":"Jigger","price":270,"description":"Small and powerful, the Jigger is the best ride for the smallest of tikes! This is the tiniest kids\xe2\x80\x99 pedal bike on the market available without a coaster brake, the Jigger is the vehicle of choice for the rare tenacious little rider raring to go.","condition":"new"}"
    3. "bicycle:1"
      1. "$"
      2. "{"pickup_zone":"POLYGON((-118.2887 34.0972, -118.1987 34.0972, -118.1987 33.9872, -118.2887 33.9872, -118.2887 34.0972))","store_location":"-118.2437,34.0522","brand":"Bicyk","model":"Hillcraft","price":1200,"description":"Kids want to ride with as little weight as possible. Especially on an incline! They may be at the age when a 27.5\" wheel bike is just too clumsy coming off a 24\" bike. The Hillcraft 26 is just the solution they need!","condition":"used"}"
    4. "bicycle:2"
      1. "$"
      2. "{"pickup_zone":"POLYGON((-87.6848 41.9331, -87.5748 41.9331, -87.5748 41.8231, -87.6848 41.8231, -87.6848 41.9331))","store_location":"-87.6298,41.8781","brand":"Nord","model":"Chook air 5","price":815,"description":"The Chook Air 5 gives kids aged six years and older a durable and uberlight mountain bike for their first experience on tracks and easy cruising through forests and fields. The lower top tube makes it easy to mount and dismount in any situation, giving your kids greater safety on the trails.","condition":"used"}"
      1. Total profile time
      2. "0"
      1. Parsing time
      2. "0"
      1. Pipeline creation time
      2. "0"
      1. Warning
      1. Iterators profile
        1. Type
        2. INTERSECT
        3. Time
        4. "0"
        5. Number of reading operations
        6. (integer) 6
        7. Child iterators
          1. Type
          2. UNION
          3. Query type
          4. UNION
          5. Time
          6. "0"
          7. Number of reading operations
          8. (integer) 6
          9. Child iterators
          1. Type
          2. UNION
          3. Query type
          4. UNION
          5. Time
          6. "0"
          7. Number of reading operations
          8. (integer) 4
          9. Child iterators 10) 1) Type 2) TEXT 3) Term 4) kids 5) Time 6) "0" 7) Number of reading operations 8) (integer) 4 9) Estimated number of matches 10) (integer) 4 11) 1) Type 2) TEXT 3) Term 4) +kid 5) Time 6) "0" 7) Number of reading operations 8) (integer) 4 9) Estimated number of matches 10) (integer) 4
          1. Type
          2. TEXT
          3. Term
          4. small
          5. Time
          6. "0"
          7. Number of reading operations
          8. (integer) 2
          9. Estimated number of matches 10) (integer) 2
          1. Type
          2. UNION
          3. Query type
          4. TAG
          5. Time
          6. "0"
          7. Number of reading operations
          8. (integer) 6
          9. Child iterators
          1. Type
          2. TAG
          3. Term
          4. new
          5. Time
          6. "0"
          7. Number of reading operations
          8. (integer) 4
          9. Estimated number of matches 10) (integer) 10
          1. Type
          2. TAG
          3. Term
          4. used
          5. Time
          6. "0"
          7. Number of reading operations
          8. (integer) 4
          9. Estimated number of matches 10) (integer) 8
      1. Result processors profile
        1. Type
        2. Index
        3. Time
        4. "0"
        5. Results processed
        6. (integer) 3
        1. Type
        2. Scorer
        3. Time
        4. "0"
        5. Results processed
        6. (integer) 3
        1. Type
        2. Sorter
        3. Time
        4. "0"
        5. Results processed
        6. (integer) 3
        1. Type
        2. Loader
        3. Time
        4. "0"
        5. Results processed
        6. (integer) 3 {{< / highlight >}}
</details> <details> <summary><b>Collect performance information about a JSON index that includes vector data.</b></summary>

For this example, you'll create a very simple vector database and index.

Index:

redis
FT.CREATE vss_idx ON JSON PREFIX 1 vec: SCHEMA $.vector AS vector VECTOR FLAT 6 TYPE FLOAT32 DIM 4 DISTANCE_METRIC L2

Database:

redis
JSON.SET vec:1 $ '{"vector":[1,1,1,1]}'
JSON.SET vec:2 $ '{"vector":[2,2,2,2]}'
JSON.SET vec:3 $ '{"vector":[3,3,3,3]}'
JSON.SET vec:4 $ '{"vector":[4,4,4,4]}'

Here's an example of running the FT.PROFILE command for a vector query.

{{< highlight bash >}} 127.0.0.1:6379> ft.profile vss_idx search query "*=>[KNN 3 @vector $query_vec]" PARAMS 2 query_vec "\x00\x00\x00@\x00\x00\x00@\x00\x00@@\x00\x00@@" SORTBY __vector_score DIALECT 2

    1. (integer) 3
    2. "vec:2"
      1. "__vector_score"
      2. "2"
      3. "$"
      4. "{"vector":[2,2,2,2]}"
    3. "vec:3"
      1. "__vector_score"
      2. "2"
      3. "$"
      4. "{"vector":[3,3,3,3]}"
    4. "vec:1"
      1. "__vector_score"
      2. "10"
      3. "$"
      4. "{"vector":[1,1,1,1]}"
      1. Total profile time
      2. "0"
      1. Parsing time
      2. "0"
      1. Pipeline creation time
      2. "0"
      1. Warning
      1. Iterators profile
        1. Type
        2. VECTOR
        3. Time
        4. "0"
        5. Number of reading operations
        6. (integer) 3
      1. Result processors profile
        1. Type
        2. Index
        3. Time
        4. "0"
        5. Results processed
        6. (integer) 3
        1. Type
        2. Metrics Applier
        3. Time
        4. "0"
        5. Results processed
        6. (integer) 3
        1. Type
        2. Sorter
        3. Time
        4. "0"
        5. Results processed
        6. (integer) 3
        1. Type
        2. Loader
        3. Time
        4. "0"
        5. Results processed
        6. (integer) 3 {{< /highlight >}}
</details>

Redis Software and Redis Cloud compatibility

| Redis Software | Redis Cloud Flexible & Annual | Redis Cloud Free & Fixed | <span style="min-width: 9em; display: table-cell">Notes</span> | |:----------------------|:-----------------|:-----------------|:------| | <span title="Supported">✅ Supported</span> | <span title="Supported">✅ Supported</span> | <span title="Supported">✅ Supported</nobr></span> | |

Return information

{{< multitabs id="ft-profile-return-info" tab1="RESP2" tab2="RESP3" >}}

One of the following:

  • [Array]({{< relref "/develop/reference/protocol-spec#arrays" >}}) with two elements: search results and profiling information.
  • [Simple error reply]({{< relref "/develop/reference/protocol-spec#simple-errors" >}}) in these cases: no such index, syntax error in query.

-tab-sep-

One of the following:

  • [Map]({{< relref "/develop/reference/protocol-spec#maps" >}}) with two keys: Results containing search results and Profile containing profiling information.
  • [Simple error reply]({{< relref "/develop/reference/protocol-spec#simple-errors" >}}) in these cases: no such index, syntax error in query.

{{< /multitabs >}}

See also

[FT.SEARCH]({{< relref "commands/ft.search/" >}}) | [FT.AGGREGATE]({{< relref "commands/ft.aggregate/" >}})

[RediSearch]({{< relref "/develop/ai/search-and-query/" >}})