biscuit
pg_biscuit : IAM-LIKE pattern matching with bitmap indexing
Overview
| ID | Extension | Package | Version | Category | License | Language |
|---|---|---|---|---|---|---|
| 2170 | biscuit
|
pg_biscuit
|
3.0.0 |
FTS
|
MIT
|
C
|
| Attribute | Has Binary | Has Library | Need Load | Has DDL | Relocatable | Trusted |
|---|---|---|---|---|---|---|
--s-d--
|
No
|
Yes
|
No
|
Yes
|
no
|
no
|
| Relationships | |
|---|---|
| Schemas | public |
| Requires | plpgsql
|
| See Also | pg_trgm
pg_similarity
fuzzystrmatch
smlar
pg_bigm
pgpcre
re2
pgroonga
|
Latest stable PGXN distribution and packaged extension version are 3.0.0; upgrading from 2.x requires REINDEX; package name is biscuit.
Packages
| Type | Repo | Version | PG Major Compatibility | Package Pattern | Dependencies |
|---|---|---|---|---|---|
| EXT | PIGSTY
|
3.0.0 |
18
17
16
15
14
|
pg_biscuit |
plpgsql |
| RPM | PIGSTY
|
3.0.0 |
18
17
16
15
14
|
biscuit_$v |
- |
| DEB | PIGSTY
|
3.0.0 |
18
17
16
15
14
|
postgresql-$v-biscuit |
- |
| Linux / PG | PG18 | PG17 | PG16 | PG15 | PG14 |
|---|---|---|---|---|---|
el8.x86_64
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
N/A
|
N/A
|
el8.aarch64
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
N/A
|
N/A
|
el9.x86_64
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
N/A
|
N/A
|
el9.aarch64
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
N/A
|
N/A
|
el10.x86_64
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
N/A
|
N/A
|
el10.aarch64
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
N/A
|
N/A
|
d12.x86_64
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
N/A
|
N/A
|
d12.aarch64
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
N/A
|
N/A
|
d13.x86_64
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
N/A
|
N/A
|
d13.aarch64
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
N/A
|
N/A
|
u22.x86_64
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
N/A
|
N/A
|
u22.aarch64
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
N/A
|
N/A
|
u24.x86_64
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
N/A
|
N/A
|
u24.aarch64
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
N/A
|
N/A
|
u26.x86_64
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
N/A
|
N/A
|
u26.aarch64
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
PIGSTY 3.0.0
|
N/A
|
N/A
|
Source
pig build pkg pg_biscuit; # build rpm/debInstall
Make sure PGDG and PIGSTY repo available:
pig repo add pgsql -u # add both repo and update cacheInstall this extension with pig:
pig install pg_biscuit; # install via package name, for the active PG version
pig install biscuit; # install by extension name, for the current active PG version
pig install biscuit -v 18; # install for PG 18
pig install biscuit -v 17; # install for PG 17
pig install biscuit -v 16; # install for PG 16Create this extension with:
CREATE EXTENSION biscuit CASCADE; -- requires plpgsqlUsage
Sources:
- Biscuit 3.0.0 on PGXN
- Biscuit 3.0.0 release
- Biscuit 3.0.0 README
- Biscuit 3.0.0 changelog
- Biscuit 3.0.0 metadata
- Biscuit 3.0.0 control file
- Biscuit 3.0.0 Makefile
- Biscuit 3.0.0 installation SQL
- Biscuit 2.5.0 to 3.0.0 upgrade SQL
biscuit 3.0.0 is a PostgreSQL 16+ positional-bitmap index access method for exact LIKE and ILIKE filtering. It is strongest for anchored patterns, _ wildcards, length predicates, and multi-column conjunctions. Version 3.0.0 stores index state in WAL-logged relation pages, so crash recovery, point-in-time recovery, physical replication, and hot-standby reads use PostgreSQL’s ordinary recovery path. It does not require shared_preload_libraries or a restart.
The project remains under active development and recommends representative staging tests. Its per-connection memory, write amplification, and cache-reload behavior make it best suited to read-mostly analytical workloads rather than continuously updated OLTP tables or very large connection pools.
Build and Query an Index
Load the data first, then create the index. The default biscuit_ops supports both case-sensitive and case-insensitive predicates. Use biscuit_like_ops or biscuit_ilike_ops when only one mode is required, avoiding the unused structure set.
CREATE EXTENSION biscuit;
CREATE INDEX message_body_biscuit_idx
ON message USING biscuit (body biscuit_like_ops);
ANALYZE message;
EXPLAIN (ANALYZE, BUFFERS)
SELECT id, body
FROM message
WHERE body LIKE 'timeout%';Expression and multi-column indexes are supported. The query must use expressions and operators compatible with the chosen operator class. Check representative plans after loading statistics, especially for unanchored patterns.
Operator Classes and Query Boundaries
biscuit_opsis the default text operator class and indexesLIKE,NOT LIKE,ILIKE, andNOT ILIKE.biscuit_like_opsindexes onlyLIKEandNOT LIKE.biscuit_ilike_opsindexes onlyILIKEandNOT ILIKE.
Biscuit returns exact matches without a heap recheck, but it is a filtering index: it does not provide ordered, backward, index-only, or unique scans, cannot back CLUSTER, and does not support regular expressions, similarity search, fuzzy search, or locale-aware collation. A B-tree with text_pattern_ops is usually a better fit for selective prefix lookups, while pg_trgm is designed for unanchored substring, regular-expression, and similarity searches.
Diagnostics and Configuration
Important inspection objects include biscuit_indexes, biscuit_status, biscuit_index_stats(oid), biscuit_index_memory_size(), biscuit_pending_list_stats(oid), and biscuit_pending_list_usage. The memory function reports the current backend’s session-local copy. total_pending_bytes is refreshed during VACUUM, so pending-list figures can lag live writes by up to one vacuum cycle.
biscuit.delta_compaction_slotsdefaults to 20000 and controls how many pending rows are tolerated before compaction. It is a privileged setting because raising it can increase reload work for other sessions.biscuit.diag_scan_tracedefaults to off and emits verbose per-scan candidate accounting. Enable it only for a focused reproducer.
Every backend lazily loads its own copy of an index and keeps it for the connection lifetime. A committed write invalidates other cached copies; their next access reloads the index rather than refreshing it incrementally. Size pools for this memory behavior and avoid interleaving frequent writes with latency-sensitive reads.
Live-index INSERT and UPDATE generate substantial WAL; monitor pg_wal, replication lag, and replication-slot retention, and consider a bounded max_slot_wal_keep_size. Bulk loading before index creation is substantially cheaper. VACUUM drains pending work but does not shrink the index; use REINDEX to reclaim index space.
Upgrade to 3.0.0
Version 3.0.0 is an incompatible on-disk format change. Updating the extension catalog does not convert existing index pages: every Biscuit index created under 2.x must be rebuilt. Plan enough maintenance time and WAL capacity for the rebuild.
ALTER EXTENSION biscuit UPDATE TO '3.0.0';
SELECT schema_name, index_name
FROM biscuit_indexes;
REINDEX INDEX CONCURRENTLY public.message_body_biscuit_idx;The unpatched upstream 3.0.0 archive ships and installs only the 2.5.0--3.0.0 step, while earlier stable packages exposed catalog versions 2.4.0 or 2.4.1. Pigsty’s 3.0.0 RPM and DEB packages restore that missing catalog path before applying the upstream step. For another source build or package, inspect pg_extension_update_paths('biscuit') before ALTER EXTENSION; regardless of the available SQL path, the mandatory REINDEX or REINDEX CONCURRENTLY remains a separate manual operation.