Skip to main content
partition_by is currently a Beta feature under active development. Syntax and internal planner behaviors may change in future releases.
By default, a ParadeDB index does not partition rows across segments. By using the partition_by option in CREATE INDEX, you can partition the index space along one or more columns: The following example uses the demo table’s rating field as a partition key. In your application, use the tenant or organization identifier that appears in your filters.
When an index includes a vector field, partition_by defaults to that field unless explicitly set.
Partitioning an index provides two key benefits:
  • Accelerating search and filter queries
  • Accelerating joins
You can also partition along multiple columns by specifying a comma-separated list:
Because ParadeDB partitions rows multi-dimensionally using a kd-tree, the order in which columns are specified in partition_by is not important.
Because 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) for partition_by depends on your query patterns and join requirements. You don’t need to add ctid to reach target_segment_count. When the listed columns can’t split a partition any further, CREATE INDEX splits it by heap position. If you list ctid, it competes with the other columns as an equal, and the fallback doesn’t apply.

Requirements for Index Partitioning

Columns specified in partition_by must meet the following constraints:
  1. Single-valued only: Multi-valued types (such as arrays TEXT[], INT[] and JSON/JSONB fields) cannot be used.
  2. Columnar indexed: The column must be columnar indexed. Scalar types (integers, floats, booleans, dates, timestamps, UUIDs) are columnar indexed by default.
  3. Tokenizer: If a text column is used in partition_by, it must use the literal tokenizer (e.g. (tenant_code::pdb.literal)).

Performance Tuning

When using partition_by, we recommend setting target_segment_count to 2–4X the parallel worker count. By default, CREATE INDEX sets target_segment_count equal to 2X max_parallel_workers_per_gather. 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.
For more details on tuning worker parallelism and segment counts, see Read Throughput. Runtime planner settings for partitioned joins are listed in the Configuration Reference.