> For the complete documentation index, see [llms.txt](https://docs.pinot.apache.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.pinot.apache.org/build-with-pinot/indexing/inverted-index.md).

# Inverted Index

The [forward index](/build-with-pinot/indexing/forward-index.md) maps document IDs (rows) to values. An inverted index reverses this mapping: it maps values to the set of document IDs that contain them. When you frequently filter on a column with predicates like EQ, IN, GT, LT, or BETWEEN, adding an inverted index can significantly improve query performance.

Pinot supports two types of inverted indexes: bitmap inverted indexes and sorted inverted indexes.

## When to use

Use an inverted index on columns that appear frequently in `WHERE` clause filters, especially for equality and membership predicates. An inverted index is a good starting point for performance tuning.

* Use a **bitmap inverted index** on unsorted columns that are filtered frequently.
* Use a **sorted inverted index** (automatic when a column is sorted) when most queries filter on the same column.

## Supported column types

Bitmap inverted indexes are supported on all data types except MAP: INT, LONG, FLOAT, DOUBLE, BIG\_DECIMAL, BOOLEAN, TIMESTAMP, STRING, JSON, BYTES. Both single-value and multi-value columns are supported.

## Bitmap inverted index

When an inverted index is enabled for an unsorted column, Pinot maintains a mapping from each value to a bitmap of document IDs. This makes value lookup take constant time O(1).

### Configuration

The recommended way to enable a bitmap inverted index:

{% code title="Recommended: fieldConfigList" %}

```json
{
  "fieldConfigList": [
    {
      "name": "playerName",
      "indexes": {
        "inverted": {}
      }
    }
  ]
}
```

{% endcode %}

Bitmap inverted indexes require dictionary IDs. If you want the column's forward index to stay RAW, configure the RAW forward index and the standalone dictionary together in `fieldConfigList`:

{% code title="RAW forward index with bitmap inverted index" %}

```json
{
  "fieldConfigList": [
    {
      "name": "playerName",
      "encodingType": "RAW",
      "indexes": {
        "dictionary": {},
        "inverted": {}
      }
    }
  ]
}
```

{% endcode %}

Pinot keeps the forward index RAW and uses the standalone dictionary for the inverted index. A field-level RAW config can also resolve with dictionary enabled when the field-level index requires it and no legacy no-dictionary setting overrides it, but the explicit `dictionary` block is the safe migration form for existing table configs.

Do not keep the column in legacy `tableIndexConfig.noDictionaryColumns` or `tableIndexConfig.noDictionaryConfig` while enabling an inverted index. Those settings still disable the dictionary, so Pinot rejects the table config instead of building a shared dictionary.

<details>

<summary>Older configuration</summary>

{% code title="Legacy: tableIndexConfig" %}

```json
{
  "tableIndexConfig": {
    "invertedIndexColumns": [
      "playerName"
    ]
  }
}
```

{% endcode %}

</details>

### When the index is created

> **Breaking Change (Apache Pinot PR #17951):** As of this version, the `indexingConfig.createInvertedIndexDuringSegmentGeneration` configuration flag is **no longer honored**. Inverted indexes are now **always created during segment generation** when configured, consistent with other index types. If you previously relied on deferring inverted index creation to segment loading time, this behavior has changed.

By default, bitmap inverted indexes are created during segment generation. Previously, this behavior was controlled by the table configuration option `indexingConfig.createInvertedIndexDuringSegmentGeneration` (which defaulted to `false`), but that flag is now deprecated and ignored.

## Sorted inverted index

When a column is sorted, Pinot can leverage sorted forward indexes for efficient filtering. The behavior depends on whether the column is dictionary-encoded:

**Dictionary-encoded sorted columns:** When a column is both sorted and dictionary-encoded, Pinot uses a sorted forward index with run-length encoding that also serves as an inverted index. This happens automatically and requires no extra configuration. The sorted inverted index provides `O(log n)` lookup time and benefits from data locality.

For example, if a query filters on a sorted `memberId` column, Pinot performs a binary search to find the range of document IDs matching the filter value. Subsequent column scans for those documents benefit from data locality because the matching rows are stored contiguously.

![Sorted inverted index](/files/-MEhLLLlm2ls7zyynlat)

**Raw (no-dictionary) sorted columns:** As of Apache Pinot 1.3.0, raw columns can now be configured as sorted columns without forcing a dictionary or inverted index. Previously, designating a raw column as sorted would cause Pinot to force-add a dictionary and inverted index, which negated the storage benefits of raw encoding. Now, you can have sorted raw columns (for example, a timestamp column) with efficient storage while maintaining sort order metadata.

A sorted inverted index on dictionary-encoded columns offers better performance than a bitmap inverted index but can only apply to columns whose data is physically sorted within each segment. Sorted raw columns provide efficient storage for sorted data without the overhead of dictionary encoding.

## Query examples

Equality filter:

```sql
SELECT COUNT(*)
FROM baseballStats
WHERE playerName = 'Barry Bonds'
```

IN filter:

```sql
SELECT yearID, hits, homeRuns
FROM baseballStats
WHERE teamID IN ('NYA', 'BOS', 'LAD')
ORDER BY yearID
```

Filter with aggregation:

```sql
SELECT teamID, SUM(hits) AS totalHits
FROM baseballStats
WHERE league = 'NL'
GROUP BY teamID
ORDER BY totalHits DESC
LIMIT 10
```

## Limitations

* Bitmap inverted indexes require dictionary IDs, but Pinot can satisfy that either with a dictionary-encoded forward index or with a standalone dictionary materialized for a RAW forward index. Legacy no-dictionary config must not disable the dictionary for that column.
* Sorted inverted indexes (on dictionary-encoded columns) only work on columns whose data is physically sorted within each segment.
* Sorted raw columns (no-dictionary) also support sort metadata without requiring an inverted index.
* MAP columns are not supported.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.pinot.apache.org/build-with-pinot/indexing/inverted-index.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
