Query Analysis
WP Dumper includes advanced database query analysis tools that help you identify performance issues, duplicate queries, N+1 problems, and optimization opportunities.
🎯 Basic Query Analysis
Starting Query Analysis
// Start logging all database queries
start_query_analysis();
// Your code that executes queries
$posts = get_posts(['post_type' => 'product']);
$users = get_users(['role' => 'customer']);
// Analyze all logged queries
dump_query_analysis();
// Stop logging
stop_query_analysis();
Quick Query Information
// Current query information
dump_query();
// Specific WP_Query analysis
$custom_query = new WP_Query(['post_type' => 'product']);
dump_wp_query($custom_query);
// Quick shortcut
queries(); // Same as dump_query()
📊 What Gets Analyzed
The query analyzer tracks:
- Query types (SELECT, INSERT, UPDATE, DELETE)
- Tables accessed and frequency
- Duplicate queries (exact matches)
- Potential slow queries (based on patterns)
- N+1 query problems (repeated similar queries)
- Query execution context (backtrace)
📈 Analysis Output
Query Summary
summary: {
total_queries: 47
unique_queries: 32
duplicate_queries: 15
execution_time: "0.234s"
memory_usage: "12.3 MB"
}
Queries by Type
by_type: {
SELECT: 42
INSERT: 3
UPDATE: 2
DELETE: 0
}
Queries by Table
by_table: {
wp_posts: 15
wp_postmeta: 12
wp_users: 8
wp_usermeta: 6
wp_options: 4
}
Duplicate Queries
duplicate_queries: [
{
query: "SELECT * FROM wp_postmeta WHERE post_id = %d"
count: 8
first_occurrence: "wp-includes/post.php:123"
locations: [
"wp-includes/post.php:123",
"wp-includes/post.php:456",
"wp-content/themes/mytheme/functions.php:89"
]
}
]
Slow Query Detection
slow_queries: [
{
query: "SELECT * FROM wp_posts WHERE post_content LIKE '%search%'"
score: 7
issues: [
"Using SELECT * instead of specific columns",
"LIKE queries can be slow without proper indexing"
]
backtrace: "wp-content/plugins/myplugin/search.php:45"
}
]
N+1 Problem Detection
n_plus_one: [
{
pattern: "SELECT * FROM wp_postmeta WHERE post_id = %d"
count: 15
description: "Potential N+1 problem: getting meta for multiple posts individually"
suggestion: "Consider using get_post_meta() with array of IDs"
}
]
🔧 Advanced Analysis
Analyzing Specific Code Blocks
function analyze_product_loading() {
start_query_analysis();
// Get products
$products = get_posts([
'post_type' => 'product',
'numberposts' => 10
]);
// This might cause N+1 problem
foreach ($products as $product) {
$meta = get_post_meta($product->ID);
$categories = get_the_terms($product->ID, 'product_category');
}
dump_query_analysis();
stop_query_analysis();
}
Comparing Before/After Optimization
// Before optimization
start_query_analysis();
$data = get_unoptimized_data();
$before_analysis = dump_query_analysis();
stop_query_analysis();
// After optimization
start_query_analysis();
$data = get_optimized_data();
$after_analysis = dump_query_analysis();
stop_query_analysis();
// Compare results
dump('Before optimization:', $before_analysis);
dump('After optimization:', $after_analysis);
🎯 Common Query Problems
1. N+1 Query Problem
Problem:
// This creates N+1 queries (1 + N where N = number of posts)
$posts = get_posts(['numberposts' => 10]);
foreach ($posts as $post) {
$meta = get_post_meta($post->ID); // 1 query per post
}
Solution:
// This creates only 2 queries total
$posts = get_posts(['numberposts' => 10]);
$post_ids = wp_list_pluck($posts, 'ID');
$all_meta = get_post_meta($post_ids); // 1 query for all meta
2. Duplicate Queries
Problem:
// These create duplicate queries
$user_1 = get_user_by('id', 123);
$user_2 = get_user_by('id', 123); // Duplicate!
$user_3 = get_user_by('id', 123); // Duplicate!
Solution:
// Cache the result
static $user_cache = [];
if (!isset($user_cache[123])) {
$user_cache[123] = get_user_by('id', 123);
}
$user = $user_cache[123];
3. Inefficient Queries
Problem:
// Inefficient: loads all data
$posts = get_posts([
'numberposts' => -1, // Gets ALL posts
'meta_query' => [
[
'key' => 'featured',
'value' => 'yes'
]
]
]);
Solution:
// Efficient: only get what you need
$posts = get_posts([
'numberposts' => 10, // Limit results
'fields' => 'ids', // Only get IDs if that's all you need
'meta_query' => [
[
'key' => 'featured',
'value' => 'yes'
]
]
]);
🔍 Analyzing Specific Scenarios
WordPress Admin Performance
// Analyze admin dashboard performance
add_action('admin_init', function() {
if (is_admin() && current_user_can('administrator')) {
start_query_analysis();
}
});
add_action('admin_footer', function() {
if (is_admin() && current_user_can('administrator')) {
dump_query_analysis();
stop_query_analysis();
}
});
Plugin Performance Analysis
// Analyze plugin activation
register_activation_hook(__FILE__, function() {
start_query_analysis();
// Plugin activation code
create_plugin_tables();
setup_default_data();
dump_query_analysis();
stop_query_analysis();
});
Theme Performance Analysis
// In functions.php
add_action('wp_head', function() {
if (WP_DEBUG && current_user_can('administrator')) {
start_query_analysis();
}
}, 1);
add_action('wp_footer', function() {
if (WP_DEBUG && current_user_can('administrator')) {
dump_query_analysis();
stop_query_analysis();
}
}, 999);
Custom Query Optimization
function optimize_product_search($search_term) {
start_query_analysis();
// Test different query approaches
$approach_1 = search_products_method_1($search_term);
dump('Method 1 queries:');
dump_query_analysis();
stop_query_analysis();
start_query_analysis();
$approach_2 = search_products_method_2($search_term);
dump('Method 2 queries:');
dump_query_analysis();
stop_query_analysis();
}
📊 Query Performance Scoring
The analyzer assigns performance scores based on:
- *SELECT ** usage (+2 points)
- ORDER BY without LIMIT (+3 points)
- LIKE queries (+2 points)
- NOT IN clauses (+3 points)
- Multiple JOINs (+2 points)
- Very long queries (+2 points)
Queries with scores ≥4 are flagged as potentially slow.
🚀 Optimization Strategies
Based on Analysis Results
- High Duplicate Count: Implement caching
- N+1 Problems: Batch queries together
- Slow Query Scores: Optimize query structure
- High Table Access: Consider database indexing
Example Optimizations
// Before: N+1 problem
function get_posts_with_meta_slow() {
$posts = get_posts(['numberposts' => 20]);
foreach ($posts as $post) {
$post->custom_meta = get_post_meta($post->ID, 'custom_field', true);
}
return $posts;
}
// After: Optimized
function get_posts_with_meta_fast() {
$posts = get_posts(['numberposts' => 20]);
$post_ids = wp_list_pluck($posts, 'ID');
// Get all meta in one query
global $wpdb;
$meta_results = $wpdb->get_results($wpdb->prepare("
SELECT post_id, meta_value
FROM {$wpdb->postmeta}
WHERE meta_key = 'custom_field'
AND post_id IN (" . implode(',', array_fill(0, count($post_ids), '%d')) . ")
", ...$post_ids));
// Map meta to posts
$meta_map = wp_list_pluck($meta_results, 'meta_value', 'post_id');
foreach ($posts as $post) {
$post->custom_meta = $meta_map[$post->ID] ?? '';
}
return $posts;
}
🔧 Global Query Functions
Available Functions
// Start/stop analysis
start_query_analysis();
stop_query_analysis();
// Dump analysis results
dump_query_analysis();
// Quick query info
dump_query(); // Current query context
queries(); // Shortcut for dump_query()
// Specific query analysis
dump_wp_query($query_object);
💡 Best Practices
- Analyze in development before deploying
- Focus on high-impact queries (most frequent/slowest)
- Test optimizations with before/after analysis
- Monitor production with selective analysis
- Use caching for repeated queries
- Batch operations when possible
- Limit query results appropriately
🔗 Related Documentation
- Performance Profiling - Overall performance analysis
- WordPress Debugging - WordPress-specific debugging
- Examples & Recipes - Real-world optimization examples