Rowid Filter — bitmap pre-filter before table accessMariaDB 11.4

See how MariaDB scans a filtering index to build a rowid bitmap, then skips table-row fetches for non-matching rows.

Parameters (Rowid Filter)

Rows returned by the main index scan (idx_date).
Percentage of rows passing the filtering index (idx_status bitmap).
Larger rows make skipped fetches more valuable (more I/O saved).

Example query this animation executes

-- idx_status on (status), idx_date on (created_date)
-- Main access via idx_date, rowid filter from idx_status
SELECT * FROM orders
WHERE  created_date > '2024-01-01'
AND    status = 'shipped';

MariaDB scans idx_status first to build a bitmap, then uses idx_date for the main scan — skipping table-row fetches for rows not in the bitmap.

What you'll see in the animation

  • Phase 1 scans the filtering index (idx_status) and sets a 1/0 bit per rowid.
  • Phase 2 scans the main index (idx_date) and checks the bitmap for each rowid.
  • Rows with bit=1 proceed to a full table fetch (green check).
  • Rows with bit=0 are skipped entirely (red cross) — no random I/O.
  • Watch the skipped-reads counter grow: every skip saves one random page read.
Ready — press Play
0.0s 0.0s

Cost readout (Rowid Filter)

Main index rows ?Total rows returned by the main index scan (idx_date). Without a rowid filter all would trigger table fetches.

Filter selectivity ?Percentage of rows whose rowid appears in the bitmap (status=shipped). Lower is better for the filter.

Rows after filter ?Rows passing the bitmap check. Only these trigger a full table-row fetch.

Rows skipped ?Rows NOT in the bitmap. Each skip avoids one random I/O page read.

Table fetches (without filter) ?Without rowid filter, every main-index row triggers a table fetch.

Table fetches (with filter) ?With rowid filter, only bitmap-passing rows trigger a table fetch.

I/O saved ?Random I/Os saved by skipping non-matching rowids. Equal to rows_skipped.

Table fetches vs main index rows (log–log, selectivity fixed)

Learn more — when does MariaDB use rowid filter?

Rowid filtering was introduced in MariaDB 10.4 and is enabled by default (optimizer_switch='rowid_filter=on'). This optimisation is not available in MySQL.

The optimizer considers rowid filter when:

1. The query accesses a table through one index (the main access path) but another index could filter out a large fraction of rows before the expensive table-row fetch.

2. The filtering index is selective enough that building the in-memory rowid bitmap and checking it per row is cheaper than fetching every row from the table.

3. The bitmap fits in memory. MariaDB allocates a compact bit-array keyed by rowid, so even millions of rows consume only a few megabytes.

Rowid filter works best when the filter index is very selective (few rows match) but the main index returns many rows. The more rows the bitmap can eliminate, the more random I/O is saved.

In EXPLAIN output you will see Rowid-ordered scan or Using rowid filter in the Extra column.

Sources: MariaDB Knowledge Base “Rowid Filtering Optimization”; MariaDB Server 10.4 Release Notes.