-
Notifications
You must be signed in to change notification settings - Fork 84
Partitioning Recipes
Partitioning begins with logical datasets added through $wpdb->add_database(). A dataset callback then chooses which dataset owns the table involved in the current query.
LudicrousDB routes queries only. Create the target schemas and tables, move the data, and arrange replication before enabling a new routing rule. Keep related tables together unless you have carefully tested cross-dataset behavior.
Use $wpdb->table rather than parsing the SQL yourself when the current query maps cleanly to one table:
$wpdb->add_callback(
function ( $query, $wpdb ) {
$tables = array(
$wpdb->base_prefix . 'posts',
$wpdb->base_prefix . 'postmeta',
);
if ( in_array( $wpdb->table, $tables, true ) ) {
return 'content';
}
return null;
}
);The returned string is a logical dataset name configured with add_database(), not necessarily a physical database name.
Do not prepend the site prefix twice. If $wpdb->base_prefix is wp_, compare it with $wpdb->base_prefix . 'posts', not $wpdb->base_prefix . 'wp_posts'.
This example groups every 100 blogs into a dataset named blogs_0, blogs_1, and so on. Network-global tables fall through to the default dataset.
$wpdb->add_callback(
function ( $query, $wpdb ) {
$pattern = '/^' . preg_quote( $wpdb->base_prefix, '/' ) . '(\d+)_/';
if ( ! preg_match( $pattern, $wpdb->table, $matches ) ) {
return null;
}
$blog_id = (int) $matches[1];
return 'blogs_' . intdiv( $blog_id, 100 );
}
);Define every possible returned dataset. Decide boundary behavior before migrating data; intdiv( 100, 100 ) returns 1, so blog 100 belongs to blogs_1 in this example.
Modulo routing produces a stable distribution when the dataset count does not change:
$wpdb->add_callback(
function ( $query, $wpdb ) {
$pattern = '/^' . preg_quote( $wpdb->base_prefix, '/' ) . '(\d+)_/';
if ( ! preg_match( $pattern, $wpdb->table, $matches ) ) {
return null;
}
$blog_id = (int) $matches[1];
return 'blogs_' . ( $blog_id % 10 );
}
);Changing 10 remaps existing blogs, so do not change the divisor without a coordinated data migration. If you need a growing fleet, store an explicit blog-to-dataset mapping in a durable service or persistent cache instead.
- Back up and test recovery.
- Create the target schema and grant only the required access.
- Copy and validate the complete table set, including metadata and plugin companion tables.
- Quiesce writes or use a proven synchronization method for the cutover.
- Enable the routing rule in staging and exercise reads, writes, upgrades, cron, and WP-CLI.
- Monitor errors and replication state before removing the old copy.
Avoid dual-writing through application callbacks unless you have designed and tested failure recovery. Database-native replication or a purpose-built migration system is usually safer.
LudicrousDB documentation · Repository · Support