# Choosing Indexes

Use this guide when you know the query shape and need a practical recommendation.

The goal is not to enable every possible index. The goal is to keep the table config aligned with the queries that matter most.

## Decision guide

| Query pattern or workload                       | Start with                                                                                                        | Why                                                        |
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| Equality filters such as `WHERE userId = '...'` | [Inverted index](/build-with-pinot/indexing/inverted-index.md)                                                    | Fast point lookups and selective filtering.                |
| `IN` filters over a small value set             | [Inverted index](/build-with-pinot/indexing/inverted-index.md)                                                    | Efficient membership testing within a segment.             |
| Bounded numeric or time filters                 | [Range index](/build-with-pinot/indexing/range-index.md)                                                          | Better than full scans for value intervals.                |
| Prefix, phrase, or token search                 | [Text search support](/build-with-pinot/indexing/text-search-support.md)                                          | Designed for search-style predicates.                      |
| Nested JSON predicates                          | [JSON index](/build-with-pinot/indexing/json-index.md)                                                            | Pushes JSON field filtering into the index.                |
| Distance or containment queries                 | [Geospatial support](/build-with-pinot/indexing/geospatial-support.md)                                            | Supports spatial workloads over geographic data.           |
| Repeated `GROUP BY` and aggregate queries       | [Star-tree index](/build-with-pinot/indexing/star-tree-index.md)                                                  | Pre-aggregates known query shapes.                         |
| Embedding similarity search                     | [Vector index](/build-with-pinot/indexing/vector-index.md)                                                        | Supports approximate nearest-neighbor lookups.             |
| Stable sort-key lookups                         | [Sorted forward index](/build-with-pinot/indexing/forward-index.md#sorted-forward-index-with-run-length-encoding) | Useful when the segment sort order matches common filters. |

## What to check before you configure an index

1. Verify the exact `WHERE`, `GROUP BY`, and function patterns in the query.
2. Check whether the column is dictionary encoded, single-value, multi-value, or JSON.
3. Confirm the index can be expressed in the current table config style.
4. Decide whether the index must exist on new segments only or should be reloaded onto existing segments.

For table-level configuration details, use [Table](/reference/configuration-reference/table.md). For an end-to-end example that applies indexes to an ingestion pipeline, use [Configure indexes](/build-with-pinot/ingestion/stream-ingestion/configure-indexes.md).

## Query validation examples

If you are validating an index choice, keep the query itself simple and representative.

```sql
SELECT COUNT(*)
FROM events
WHERE userId = 'u123'
```

```sql
SELECT campaign, SUM(impressions)
FROM events
WHERE eventDate BETWEEN 20240301 AND 20240331
GROUP BY campaign
```

```sql
SELECT title
FROM documents
WHERE TEXT_MATCH(title, 'pinot query engine')
```

```sql
SELECT id
FROM embeddings
WHERE VECTOR_SIMILARITY(embedding, ARRAY[0.12, 0.18, 0.33], 10)
```

## Configuration style

Prefer the modern column-level configuration in `fieldConfigList` when the index supports it. Use legacy table-level settings only when you are maintaining an older table or following a migration path.

If you need to change an index on an existing table, confirm whether the change can be applied incrementally or whether the segments need to be reloaded.

## What this page covered

This page mapped common Pinot query patterns to the indexes that usually fit them best and highlighted the checks to do before changing table config.

## Next step

Open the specific index page for the workload you are tuning, then compare it with the table config and query examples for that workload.

## Related pages

* [Indexing](/build-with-pinot/indexing.md)
* [Table](/reference/configuration-reference/table.md)
* [Configure indexes](/build-with-pinot/ingestion/stream-ingestion/configure-indexes.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.pinot.apache.org/build-with-pinot/indexing/choosing-indexes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
