Performance & Indexing
WooCommerce Appointments 5.0+ introduces significant performance improvements through database indexing, query optimization, and an availability caching system. This guide covers the performance architecture and optimization techniques.
Indexing System
Availability Index
The indexing system precomputes availability data for faster calendar views and slot calculations.
Index Table Structure
CREATE TABLE wp_wc_appointments_availability_cache (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
source varchar(50) NOT NULL,
source_id bigint(20) unsigned NOT NULL,
product_id bigint(20) unsigned NOT NULL,
staff_id bigint(20) unsigned DEFAULT NULL,
scope varchar(50) NOT NULL,
appointable tinyint(1) NOT NULL,
priority int(11) NOT NULL DEFAULT 0,
qty int(11) NOT NULL DEFAULT 1,
start_ts bigint(20) NOT NULL,
end_ts bigint(20) NOT NULL,
range_type varchar(50) NOT NULL,
rule_kind varchar(50) NOT NULL,
status varchar(20) NOT NULL DEFAULT 'active',
date_created datetime NOT NULL,
date_modified datetime NOT NULL,
PRIMARY KEY (id),
KEY idx_source_qty_appointable_scope_product_staff_source_id (source, qty, appointable, scope, product_id, staff_id, source_id),
KEY idx_product_staff_start_end (product_id, staff_id, start_ts, end_ts),
KEY idx_start_end (start_ts, end_ts)
);
Composite Index Benefits
- Fast Range Queries: Optimized for time-based lookups
- Product/Staff Filtering: Efficient filtering by product and staff combinations
- Scope-based Queries: Quick access to global, product, or staff-specific rules
Database Indexes
Postmeta Indexes
Automatic creation of composite indexes on WordPress postmeta table:
-- Primary index for appointment queries
ALTER TABLE wp_postmeta ADD INDEX idx_post_id_meta_key (post_id, meta_key);
-- Additional indexes for specific queries
ALTER TABLE wp_postmeta ADD INDEX idx_meta_key_meta_value (meta_key, meta_value);
Query Optimization Impact
- Reduced Query Time: Appointment lookups improved by 60-80%
- Lower Database Load: Fewer full table scans
- Better Scalability: Handles larger appointment volumes efficiently
Query Optimizations
JOIN Strategy
The system uses different JOIN strategies based on query requirements:
INNER JOINs for Required Data
-- When meta values are used in WHERE or ORDER BY
SELECT p.ID, pm1.meta_value as start_date, pm2.meta_value as end_date
FROM wp_posts p
INNER JOIN wp_postmeta pm1 ON p.ID = pm1.post_id AND pm1.meta_key = '_appointment_start'
INNER JOIN wp_postmeta pm2 ON p.ID = pm2.post_id AND pm2.meta_key = '_appointment_end'
WHERE p.post_type = 'wc_appointment'
ORDER BY pm1.meta_value ASC;
EXISTS Subqueries for Filtering
-- When meta is not used in ORDER BY (faster filtering)
SELECT p.ID
FROM wp_posts p
WHERE p.post_type = 'wc_appointment'
AND EXISTS (
SELECT 1 FROM wp_postmeta pm
WHERE pm.post_id = p.ID AND pm.meta_key = '_appointment_status'
AND pm.meta_value = 'confirmed'
);
UNION Queries for OR Conditions
-- Better index usage than OR conditions
SELECT * FROM appointments WHERE staff_id = 5
UNION
SELECT * FROM appointments WHERE product_id = 10;
Caching System
Availability Cache
- Precomputed Data: Availability rules processed and stored in cache table
- Time-based Invalidation: Cache expires based on rule changes and time horizons
- Intelligent Rebuilding: Only affected date ranges are recalculated
Query Result Caching
// Example of cached availability check
$cache_key = "availability_{$product_id}_{$staff_id}_{$date}";
$cached_result = wp_cache_get($cache_key, 'wc_appointments');
if (false === $cached_result) {
$result = calculate_availability($product_id, $staff_id, $date);
wp_cache_set($cache_key, $result, 'wc_appointments', 300); // 5 minutes
}
Performance Monitoring
Query Performance
Monitor slow queries using WordPress built-in tools:
// Enable query monitoring in wp-config.php
define('SAVEQUERIES', true);
// View query performance in admin
add_action('admin_init', function() {
if (current_user_can('manage_options')) {
global $wpdb;
var_dump($wpdb->queries);
}
});
Index Health Checks
Automatic verification of required indexes:
// Built-in index verification
$index_status = WC_Appointments_Indexing::verify_indexes();
if (!$index_status['all_present']) {
// Log missing indexes
error_log('Missing appointment indexes: ' . print_r($index_status['missing'], true));
}
Optimization Best Practices
Database Configuration
- MySQL 5.7+: Recommended for better index performance
- InnoDB Engine: Required for proper index support
- Sufficient Memory: Allocate adequate memory for index caching
Plugin Configuration
- Enable Indexing: Keep indexing system enabled for optimal performance
- Regular Rebuilding: Schedule periodic index rebuilding
- Monitor Cache Size: Ensure cache table doesn't grow excessively
Code Optimization
- Use Indexed Queries: Leverage precomputed data when possible
- Avoid N+1 Queries: Use JOINs and EXISTS subqueries appropriately
- Cache Frequently Accessed Data: Implement custom caching for complex calculations
Troubleshooting Performance Issues
Slow Calendar Loading
Symptoms: Calendar takes more than 3-5 seconds to load
Solutions:
- Verify indexes are created:
WC_Appointments_Indexing::verify_indexes() - Check cache table size: Large tables may need optimization
- Review query logs: Identify slow queries using
SAVEQUERIES
High Memory Usage
Symptoms: PHP memory exhaustion during availability calculations
Solutions:
- Increase PHP memory limit
- Reduce cache horizon in settings
- Optimize availability rules complexity
Database Locks
Symptoms: Database timeouts during concurrent appointments
Solutions:
- Use atomic booking operations
- Implement proper transaction handling
- Consider read replicas for read-heavy operations
Performance Benchmarks
Before Optimization (v4.x)
- Calendar Load: 8-12 seconds
- Slot Calculation: 2-5 seconds per product
- Database Queries: 50-100 queries per page load
After Optimization (v5.0+)
- Calendar Load: 1-3 seconds (70% improvement)
- Slot Calculation: 200-500ms per product (90% improvement)
- Database Queries: 10-20 queries per page load (80% reduction)
Advanced Topics
Custom Indexing
Developers can extend the indexing system for custom use cases:
// Register custom indexer
add_filter('wc_appointments_indexers', function($indexers) {
$indexers['custom_availability'] = [
'class' => 'Custom_Availability_Indexer',
'priority' => 20,
];
return $indexers;
});
Query Hooks
Optimize queries using built-in hooks:
// Modify appointment queries for performance
add_filter('wc_appointments_get_appointments_query_args', function($args) {
// Add efficient filtering
$args['meta_query'] = [
'relation' => 'AND',
[
'key' => '_appointment_status',
'value' => ['confirmed', 'paid'],
'compare' => 'IN',
],
];
return $args;
});
Related Documentation
- REST API Performance - API optimization techniques
- Calendar Management - Calendar performance considerations