--- acl_categories: - '@read' - '@search' arguments: - name: index type: string - arguments: - name: search token: SEARCH type: pure-token - name: aggregate token: AGGREGATE type: pure-token name: querytype type: oneof - name: limited optional: true token: LIMITED type: pure-token - name: queryword token: QUERY type: pure-token - name: query type: string categories: - docs - develop - stack - oss - rs - rc - oss - kubernetes - clients command_flags: - readonly complexity: O(N) description: Performs a `FT.SEARCH` or `FT.AGGREGATE` command and collects performance information group: search hidden: false linkTitle: FT.PROFILE module: Search railroad_diagram: /images/railroad/ft.profile.svg since: 2.2.0 stack_path: docs/interact/search-and-query summary: Performs a `FT.SEARCH` or `FT.AGGREGATE` command and collects performance information syntax_fmt: FT.PROFILE index [LIMITED] QUERY query title: FT.PROFILE --- Apply [`FT.SEARCH`]({{< relref "commands/ft.search/" >}}) or [`FT.AGGREGATE`]({{< relref "commands/ft.aggregate/" >}}) command to collect performance details. For usage, see [Examples](#examples). ## Required arguments
index is the name of an index created using [`FT.CREATE`]({{< relref "commands/ft.create/" >}}).
SEARCH | AGGREGATE represents the profile type, either [`FT.SEARCH`]({{< relref "commands/ft.search/" >}}) or [`FT.AGGREGATE`]({{< relref "commands/ft.aggregate/" >}}).
LIMITED removes details of any `reader` iterators.
QUERY {query} is the query string, sent to `FT.SEARCH` or `FT.AGGREGATE`.
Note: 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. ## 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 name | Definition | |:-- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `Shard ID` | String 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` `time` | The total run time (ms) of the query. Normally just a few ms. | | `Parsing` `time` | The time (ms) spent parsing the query and its parameters into a query plan. Normally just a few ms. | | `Pipeline` `creation` `time` | The 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` `time` | In 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. | | `Warning` | Errors that occurred during query execution. | | `Internal` `cursor` `reads` | The 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](#notes-onvector-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: | Mode | Description | |:-- |:-- | | `STANDARD_KNN` | Pure KNN vector search without filters. | | `RANGE_QUERY` | Range-based vector search. Used with `VECTOR_RANGE` queries. | | `HYBRID_ADHOC_BF` | Ad-hoc brute force for filtered queries. Iterates through results that pass the filter and calculates distances on-the-fly. | | `HYBRID_BATCHES` | Batch-based filtered search. Retrieves top vectors from the index in batches and checks which ones pass the filter. | | `HYBRID_BATCHES_TO_ADHOC_BF`| Dynamic 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 name | Definition | |:-- |:-- | | `Batches number` | Total number of batch iterations executed during the search. | | `Largest batch size`| The 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 Query Engine. 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. | Type | Definition | |:-- |:-- | | `Metrics` `Applier` | The `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. | | `Index` | The `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). | | `Scorer` | The `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. | | `Sorter` | The `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. | | `Loader` | The `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-Loader` | The `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. | | `Highlighter` | The `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/Limiter` | The `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. | | `Counter` | The `Counter` processor counts the total number of matching results. Used when running queries with `LIMIT 0 0` to return only the count. | | `Grouper` | The `Grouper` processor groups results by field values. Used with `GROUPBY` in `FT.AGGREGATE` queries. | | `Projector` | The `Projector` processor applies field transformations. Used with `APPLY` in `FT.AGGREGATE` queries. | | `Network` | Collects 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 name | Definition | |:-- |:-- | | `Total coordinator time` | Time measured from the beginning of query execution until all shards have completed query execution. (ms) | | `Post-processing time` | The time spent generating the FT.PROFILE output (overhead) (ms). | ## Examples
Collect performance information about a simple JSON index. 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) 1) (integer) 3 2) "bicycle:0" 3) 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\"}" 4) "bicycle:1" 5) 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\"}" 6) "bicycle:2" 7) 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\"}" 2) 1) 1) Total profile time 2) "0" 2) 1) Parsing time 2) "0" 3) 1) Pipeline creation time 2) "0" 4) 1) Warning 5) 1) Iterators profile 2) 1) Type 2) INTERSECT 3) Time 4) "0" 5) Number of reading operations 6) (integer) 6 7) Child iterators 8) 1) Type 2) UNION 3) Query type 4) UNION 5) Time 6) "0" 7) Number of reading operations 8) (integer) 6 9) Child iterators 10) 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 11) 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 9) 1) Type 2) UNION 3) Query type 4) TAG 5) Time 6) "0" 7) Number of reading operations 8) (integer) 6 9) Child iterators 10) 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 11) 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 6) 1) Result processors profile 2) 1) Type 2) Index 3) Time 4) "0" 5) Results processed 6) (integer) 3 3) 1) Type 2) Scorer 3) Time 4) "0" 5) Results processed 6) (integer) 3 4) 1) Type 2) Sorter 3) Time 4) "0" 5) Results processed 6) (integer) 3 5) 1) Type 2) Loader 3) Time 4) "0" 5) Results processed 6) (integer) 3 {{< / highlight >}}
Collect performance information about a JSON index that includes vector data. 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) 1) (integer) 3 2) "vec:2" 3) 1) "__vector_score" 2) "2" 3) "$" 4) "{\"vector\":[2,2,2,2]}" 4) "vec:3" 5) 1) "__vector_score" 2) "2" 3) "$" 4) "{\"vector\":[3,3,3,3]}" 6) "vec:1" 7) 1) "__vector_score" 2) "10" 3) "$" 4) "{\"vector\":[1,1,1,1]}" 2) 1) 1) Total profile time 2) "0" 2) 1) Parsing time 2) "0" 3) 1) Pipeline creation time 2) "0" 4) 1) Warning 5) 1) Iterators profile 2) 1) Type 2) VECTOR 3) Time 4) "0" 5) Number of reading operations 6) (integer) 3 6) 1) Result processors profile 2) 1) Type 2) Index 3) Time 4) "0" 5) Results processed 6) (integer) 3 3) 1) Type 2) Metrics Applier 3) Time 4) "0" 5) Results processed 6) (integer) 3 4) 1) Type 2) Sorter 3) Time 4) "0" 5) Results processed 6) (integer) 3 5) 1) Type 2) Loader 3) Time 4) "0" 5) Results processed 6) (integer) 3 {{< /highlight >}}
## Redis Software and Redis Cloud compatibility | Redis
Software | Redis Cloud
Flexible & Annual | Redis Cloud
Free & Fixed | Notes | |:----------------------|:-----------------|:-----------------|:------| | ✅ Supported | ✅ Supported | ✅ Supported | | ## 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/" >}}) ## Related topics [RediSearch]({{< relref "/develop/ai/search-and-query/" >}})