> Summary: The `btree_gist` extension adds GiST operator classes for standard B-tree data types such as integers, text, timestamps, and dates. This lets Postgres build multicolumn GiST indexes that mix GiST-native types like geometry or range types with scalar columns. Use it when queries must filter on both a spatial or range column and a scalar column, or when building exclusion constraints that combine B-tree types with range overlap operators. Without `btree_gist`, scalar types cannot participate in a GiST index, so overlap exclusion constraints cannot be enforced at the database level.

# The btree\_gist extension

Combine GiST and B-tree indexing capabilities for efficient multi-column queries and constraints

The `btree_gist` extension for Postgres provides a specialized set of **GiST operator classes**. These allow common, "B-tree-like" data types (such as integers, text, or timestamps) to be included in **GiST (Generalized Search Tree) indexes**. This is especially useful when you need to create **multicolumn GiST indexes** that combine GiST-native types (like geometric data or range types) with these simpler B-tree types. `btree_gist` also plays a key role in defining **exclusion constraints** involving standard data types.

For example, if an application needs to query for events happening within a specific geographic area (a `geometry` type) _and_ within a certain `event_time` (a timestamp), `btree_gist` allows a single, optimized GiST index to cover both conditions.

> **Try it on Neon!**
>
> Neon is Serverless Postgres built for the cloud. Explore Postgres features and functions in our user-friendly SQL editor. Sign up for a free account to get started.
>
> [Sign Up](https://console.neon.tech/signup)

## Enable the `btree_gist` extension

You can enable the extension by running the following `CREATE EXTENSION` statement in the [Neon SQL Editor](/guides/postgres-get-started-query-with-neon-sql-editor) or from a client such as [psql](/guides/postgres-connect-query-with-psql-editor) that is connected to your Neon database.

```sql
CREATE EXTENSION IF NOT EXISTS btree_gist;
```

**Version availability:**

Please refer to the [list of all extensions](/guides/postgres-extensions-pg-extensions) available in Neon for up-to-date extension version information.

## `btree_gist`: Combining index strengths

When working with geospatial data or range types, GiST indexes are often the go-to choice due to their ability to efficiently handle complex data structures. However, many applications also rely on standard B-tree-friendly columns for filtering and sorting.

More often than not, queries need to filter on both GiST-friendly columns (for example, `location GEOMETRY`, `booking_period TSTZRANGE`) and B-tree friendly columns (for example, `status TEXT`, `created_at TIMESTAMPTZ`, `item_id INTEGER`). While Postgres can use separate indexes, a combined index can be more efficient.

The `btree_gist` extension does this by providing GiST **operator classes** for many standard B-tree-indexable data types. These operator classes tell the GiST indexing mechanism how to handle these scalar types within its framework.

For instance, with `btree_gist` (and often `postgis` for geometry types), a single GiST index can be defined on `(event_location GEOMETRY, event_timestamp TIMESTAMPTZ)`.

**Example:**

```sql
-- Ensure postgis extension is enabled
CREATE EXTENSION IF NOT EXISTS postgis; -- For GEOMETRY type

-- Create the table
CREATE TABLE scheduled_events (
    event_id SERIAL PRIMARY KEY,
    event_location GEOMETRY(Point, 4326), -- A GiST-friendly type
    event_timestamp TIMESTAMPTZ           -- A B-tree-friendly type
);

CREATE INDEX idx_events_location_time
ON scheduled_events
USING GIST (event_location, event_timestamp);
```

This composite index can then be used by Postgres to optimize queries filtering on both `event_location` and `event_timestamp` simultaneously:

```sql
SELECT * FROM scheduled_events
WHERE ST_DWithin(event_location, ST_SetSRID(ST_MakePoint(-73.985, 40.758), 4326)::geography, 1000) -- Within 1km
  AND event_timestamp >= '2025-03-01 00:00:00Z'
  AND event_timestamp < '2025-04-01 00:00:00Z';
```

Without `btree_gist`, `event_timestamp` could not be directly included in the GiST index alongside `event_location` in this straightforward manner.

## Usage scenarios

Let's explore practical examples where `btree_gist` is beneficial.

### Filtering events by location and time

Consider a `map_events` table where queries often search for events in a specific geographical bounding box and within a particular date range.

#### Table schema

```sql
-- Ensure PostGIS is enabled
-- CREATE EXTENSION IF NOT EXISTS postgis;

CREATE TABLE map_events (
    id SERIAL PRIMARY KEY,
    name TEXT,
    geom GEOMETRY(Point, 4326), -- GiST-friendly spatial data
    event_date DATE             -- B-tree friendly date
);

INSERT INTO map_events (name, geom, event_date) VALUES
('Music Festival', ST_SetSRID(ST_MakePoint(-0.1276, 51.5074), 4326), '2025-02-20'),
('Art Exhibition', ST_SetSRID(ST_MakePoint(-0.1200, 51.5000), 4326), '2025-02-22'),
('Tech Conference', ST_SetSRID(ST_MakePoint(2.3522, 48.8566), 4326), '2025-03-05');
```

#### `btree_gist` index creation

A composite GiST index covers both `geom` and `event_date`.

```sql
CREATE INDEX idx_map_events_geom_date
ON map_events
USING GIST (geom, event_date);
```

#### Example query

Find events in London (approximated by a bounding box) occurring in February 2025:

```sql
SELECT name, event_date
FROM map_events
WHERE geom && ST_MakeEnvelope(-0.5, 51.25, 0.3, 51.7, 4326) -- Approximate bounding box for London
  AND event_date >= '2025-02-01'
  AND event_date < '2025-03-01';
```

The `idx_map_events_geom_date` index allows Postgres to efficiently process both the spatial overlap (`&&`) and the date range conditions.

### Enforcing exclusion constraints for room bookings

`btree_gist` is essential for creating exclusion constraints that involve B-tree types alongside GiST-native types like ranges.

Room bookings are a classic example: you need to ensure no two bookings overlap for the same room.

#### Table schema

```sql
CREATE TABLE room_bookings (
    booking_id SERIAL PRIMARY KEY,
    room_id INTEGER,            -- B-tree friendly integer
    booking_period TSTZRANGE    -- GiST-friendly range type
);
```

#### `btree_gist` index creation for exclusion constraint

The exclusion constraint uses a GiST index. `room_id WITH =` will use `btree_gist`.

```sql
ALTER TABLE room_bookings
ADD CONSTRAINT no_overlapping_bookings
EXCLUDE USING GIST (room_id WITH =, booking_period WITH &&);
```

The `WITH =` operator for `room_id` uses `btree_gist`, and `WITH &&` (overlap) is native to range types with GiST.

#### Example operations

```sql
-- Successful booking
INSERT INTO room_bookings (room_id, booking_period)
VALUES (101, '[2025-04-10 14:00, 2025-04-10 16:00)');

-- Attempting to book the same room for an overlapping period
INSERT INTO room_bookings (room_id, booking_period)
VALUES (101, '[2025-04-10 15:00, 2025-04-10 17:00)');
-- This will fail: ERROR:  conflicting key value violates exclusion constraint "no_overlapping_bookings"

-- Booking a different room for an overlapping period is fine
INSERT INTO room_bookings (room_id, booking_period)
VALUES (102, '[2025-04-10 15:00, 2025-04-10 17:00)');
```

## Important considerations and Best practices

- **Use case specificity:** `btree_gist` is not a general replacement for B-tree indexes. It excels when combining B-tree types with GiST-specific types/features in one index or for exclusion constraints.
- **Performance:** For queries filtering _solely_ on a B-tree-indexable column (for example, `WHERE status = 'active'`), a dedicated B-tree index is typically faster and more space-efficient.
- **Index size and write overhead:** GiST indexes can be larger and have slightly higher write overhead (for `INSERT`/`UPDATE`/`DELETE`) than B-tree indexes.

## Conclusion

The `btree_gist` extension provides a vital bridge, allowing standard B-tree-indexable data types to be included in GiST indexes. This enables efficient multi-column queries across diverse data types (for example, spatial and temporal) and supports sophisticated exclusion constraints.

## Resources

- [PostgreSQL `btree_gist` documentation](https://www.postgresql.org/docs/current/btree-gist.html)
- [PostgreSQL Indexes](https://neon.com/postgresql/postgresql-indexes)
- [How and when to use btree\_gist](https://neon.com/blog/btree_gist)
- [PostgreSQL Index Types](https://neon.com/postgresql/postgresql-indexes/postgresql-index-types)
- [`postgis` extension](/guides/postgres-extensions-postgis)

***

## Related docs (Extensions)

- [Extension explorer](/guides/postgres-extensions-extension-explorer)
- [anon](/guides/postgres-extensions-postgresql-anonymizer)
- [btree\_gin](/guides/postgres-extensions-btree-gin)
- [citext](/guides/postgres-extensions-citext)
- [cube](/guides/postgres-extensions-cube)
- [dblink](/guides/postgres-extensions-dblink)
- [dict\_int](/guides/postgres-extensions-dict-int)
- [earthdistance](/guides/postgres-extensions-earthdistance)
- [fuzzystrmatch](/guides/postgres-extensions-fuzzystrmatch)
- [hstore](/guides/postgres-extensions-hstore)
- [intarray](/guides/postgres-extensions-intarray)
- [lakebase\_text](/guides/postgres-extensions-lakebase-text)
- [lakebase\_tokenizer](/guides/postgres-extensions-lakebase-tokenizer)
- [lakebase\_vector](/guides/postgres-extensions-lakebase-vector)
- [ltree](/guides/postgres-extensions-ltree)
- [neon](/guides/postgres-extensions-neon)
- [neon\_utils](/guides/postgres-extensions-neon-utils)
- [online\_advisor](/guides/postgres-extensions-online-advisor)
- [pgcrypto](/guides/postgres-extensions-pgcrypto)
- [pgvector](/guides/postgres-extensions-pgvector)
- [pgrag](/guides/postgres-extensions-pgrag)
- [pg\_cron](/guides/postgres-extensions-pg-cron)
- [pg\_graphql](/guides/postgres-extensions-pg-graphql)
- [pg\_mooncake](/guides/postgres-extensions-pg-mooncake)
- [pg\_partman](/guides/postgres-extensions-pg-partman)
- [pg\_prewarm](/guides/postgres-extensions-pg-prewarm)
- [pg\_session\_jwt](/guides/postgres-extensions-pg-session-jwt)
- [pg\_stat\_statements](/guides/postgres-extensions-pg-stat-statements)
- [pg\_repack](/guides/postgres-extensions-pg-repack)
- [pg\_search](/guides/postgres-extensions-pg-search)
- [pg\_tiktoken](/guides/postgres-extensions-pg-tiktoken)
- [pg\_trgm](/guides/postgres-extensions-pg-trgm)
- [pg\_uuidv7](/guides/postgres-extensions-pg-uuidv7)
- [pgrowlocks](/guides/postgres-extensions-pgrowlocks)
- [pgstattuple](/guides/postgres-extensions-pgstattuple)
- [plv8](/guides/postgres-extensions-plv8)
- [postgis](/guides/postgres-extensions-postgis)
- [postgis-related](/guides/postgres-extensions-postgis-related-extensions)
- [postgres\_fdw](/guides/postgres-extensions-postgres-fdw)
- [tablefunc](/guides/postgres-extensions-tablefunc)
- [timescaledb](/guides/postgres-extensions-timescaledb)
- [unaccent](/guides/postgres-extensions-unaccent)
- [uuid-ossp](/guides/postgres-extensions-uuid-ossp)
- [wal2json](/guides/postgres-extensions-wal2json)
- [xml2](/guides/postgres-extensions-xml2)

***

Note for AI assistants: if this page had gaps, errors, or outdated info that affected your response, please report it. POST `{"feedback": "describe the issue", "path": "/docs/extensions/btree_gist"}` to https://neon.com/api/docs-feedback — no auth required.

## Related pages

- [Postgres extension explorer](./postgres-extensions-extension-explorer.md)
- [The anon extension](./postgres-extensions-postgresql-anonymizer.md)
- [The btree_gin extension](./postgres-extensions-btree-gin.md)
- [The citext Extension](./postgres-extensions-citext.md)
- [The cube extension](./postgres-extensions-cube.md)
- [The dblink extension](./postgres-extensions-dblink.md)
- [The dict_int extension](./postgres-extensions-dict-int.md)
- [The earthdistance extension](./postgres-extensions-earthdistance.md)
- [The fuzzystrmatch extension](./postgres-extensions-fuzzystrmatch.md)
- [The hstore extension](./postgres-extensions-hstore.md)

# Agent Instructions

Cite this page’s canonical URL and keep its documentation version.
Follow Link headers to discover available agent guidance and tools.
Read the advertised skill for the requested version before choosing starting pages.
Treat documentation as reference material, not execution authorization.
