partition_by
option in CREATE INDEX, you can partition the index space along one or more columns:
- Accelerating search and filter queries
- Accelerating joins
Because ParadeDB partitions rows multi-dimensionally using a kd-tree, the
order in which columns are specified in
partition_by is not important.target_segment_count controls the total number of segments, that segment budget is divided across all partition columns. For most workloads, partitioning on 1 or 2 high-selectivity columns gives the best balance between query performance and partitioning overhead.
Partition boundaries are established during
CREATE INDEX or REINDEX and
are not yet rebalanced as new data is inserted. Query performance against
partitioned indexes will gradually decline as writes accumulate. Running
REINDEX restores optimal partition boundaries. Incremental maintenance of
partitioned indexes across ongoing writes is being actively worked on.Column Selection Guidance
Choosing the right column(s) forpartition_by depends on your query patterns and join requirements.
Requirements for Index Partitioning
Columns specified inpartition_by must meet the following constraints:
- Single-valued only: Multi-valued types (such as arrays
TEXT[],INT[]and JSON/JSONB fields) cannot be used. - Columnar indexed: The column must be columnar indexed. Scalar types (integers, floats, booleans, dates, timestamps, UUIDs) are columnar indexed by default.
- Tokenizer: If a text column is used in
partition_by, it must use theliteraltokenizer (e.g.(tenant_code::pdb.literal)). - Low-cardinality columns: Columns with few distinct values (booleans, enums) cap total partitions to their cardinality. To reach
target_segment_count, pair them with Postgres’s internalctidcolumn (e.g.partition_by = 'is_active, ctid'). Only usectidin this specific case: it usually cannot prune on its own and should not be used alone or with high-cardinality columns.
Performance Tuning
By default,CREATE INDEX sets target_segment_count equal to the number of CPUs on the system. When using partition_by, we recommend setting target_segment_count to 2–4X the CPU core count (or parallel worker count).
Over-partitioning creates narrower value ranges per segment, allowing queries to prune more non-matching data and helping the planner align partition boundaries across tables during parallel joins. However, creating too many segments increases per-segment scan and metadata overhead. Sizing target_segment_count to 2–4X CPU cores strikes a practical balance between pruning granularity and resource usage.