A production-grade query performance analyzer for Java applications that automatically detects N+1 queries, analyzes query plans, and provides actionable recommendations. Works with Hibernate, MyBatis, jOOQ, Spring JDBC, or any JDBC-based framework.
- Test Support -
@NoNPlusOneannotation to catch N+1 in unit tests - Detection Modes - THRESHOLD, CONFIDENCE, and HYBRID modes
- Framework Detection - Automatic detection of Hibernate, MyBatis, jOOQ, Spring JDBC
- Framework-Specific Suggestions - Targeted fix recommendations
- Relationship Inference - Infers parent-child relationships from SQL patterns
Maven:
<dependency>
<groupId>io.github.query-analyzer</groupId>
<artifactId>query-analyzer-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>Gradle:
implementation 'io.github.query-analyzer:query-analyzer-spring-boot-starter:1.2.5'That's it! Query Analyzer will automatically:
- Detect N+1 queries
- Analyze query plans (MySQL, PostgreSQL, H2)
- Provide specific recommendations
- Track issues by endpoint
Simple:
query-analyzer:
enabled: true
profile: BALANCED # STRICT, BALANCED, or LENIENTProduction:
query-analyzer:
enabled: true
profile: LENIENT
detection:
min-confidence: 0.6
plan:
enabled: true
max-per-request: 3
timeout-seconds: 2
reporter:
minimum-severity: WARNINGSee Configuration Guide for complete reference.
Prevent N+1 regressions with the @NoNPlusOne annotation:
import io.queryanalyzer.test.NoNPlusOne;
import io.queryanalyzer.test.NoNPlusOneExtension;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
@ExtendWith(NoNPlusOneExtension.class)
class UserServiceTest {
@Autowired
private UserService userService;
@Test
@NoNPlusOne
void findAllUsers_shouldNotCauseNPlusOne() {
userService.findAllWithOrders();
// Test fails if N+1 detected
}
@Test
@NoNPlusOne(threshold = 5, ignore = {"audit_log"})
void customSettings() {
userService.findAll();
}
}See Testing Guide for details.
- Automatic N+1 Detection - Identifies lazy loading issues without code changes
- Slow Query Monitoring - Tracks execution times with configurable thresholds
- Query Plan Analysis - Analyzes EXPLAIN output to find performance issues
- Actionable Recommendations - Suggests specific fixes with code examples
- THRESHOLD - Simple count-based detection (best for testing)
- CONFIDENCE - Multi-signal scoring with stack trace and timing analysis
- HYBRID - Both must agree (fewest false positives)
- Hibernate/JPA - JOIN FETCH, @BatchSize, @EntityGraph suggestions
- MyBatis - Nested result mapping suggestions
- jOOQ - multiset() and JOIN suggestions
- Spring JDBC - IN clause batching suggestions
- Thread-Safe - Complete request isolation using ThreadLocal
- Rate-Limited - Prevents overwhelming database with plan analysis
- Historical Tracking - Store and analyze issues over time
- Request Context - Associate issues with endpoints and users
- Minimal Overhead - <3ms per request without plan analysis
Query Analyzer uses a transparent proxy pattern to intercept JDBC calls without modifying your code:
The system operates through six layers:
| Layer | Components | Purpose |
|---|---|---|
| Application | Controller, Service, Repository | Your code (unchanged) |
| HTTP Interception | QueryAnalysisFilter | Starts/ends tracking per request |
| Query Tracking | RequestContextHolder | ThreadLocal storage for queries |
| Proxy | DataSource, Connection, Statement | Intercepts JDBC calls |
| Analysis | NPlusOneDetector, SlowQueryDetector | Identifies issues |
| Reporting | ConsoleReporter | Outputs results |
The request lifecycle showing how Query Analyzer intercepts and analyzes queries:
Flow:
- HTTP request arrives at your application
QueryAnalysisFilterstarts tracking viaRequestContextHolder- Your controller/service code executes normally
DataSourceProxywraps connections transparentlyStatementProxyintercepts every query and records it- Queries execute against the database
- After request completes,
QueryAnalysisOrchestratorruns NPlusOneDetectoranalyzes recorded queries for patternsConsoleReporteroutputs warnings with fix suggestions
See Architecture Documentation for detailed component diagrams.
cd query-analyzer-examples/example-basic
mvn spring-boot:runThen try these endpoints:
BAD Example (triggers N+1):
curl http://localhost:8080/api/examples/bad/n-plus-oneConsole shows N+1 detection with suggestions.
GOOD Example (optimized):
curl http://localhost:8080/api/examples/good/n-plus-one-fixedConsole shows "No Issues Found".
See all examples: Examples README
@Component
public class CartesianProductDetector implements QueryDetector {
@Override
public String getName() {
return "cartesian-product";
}
@Override
public List<QueryIssue> detect(List<QueryInfo> queries) {
// Your custom detection logic
return issues;
}
}Spring Boot automatically discovers and registers your detector.
@Component
public class SlackReporter implements QueryReporter {
@Override
public void report(List<QueryIssue> issues) {
issues.forEach(issue -> slack.send(issue));
}
}- Getting Started Guide - Installation and basic usage
- Testing Guide - Using @NoNPlusOne annotation
- Examples - Working examples
- Configuration Guide - Complete configuration reference
- Detection Modes - THRESHOLD vs CONFIDENCE vs HYBRID
- Framework Support - Hibernate, MyBatis, jOOQ, Spring JDBC
- Architecture Overview - System design and components
- API Reference - Complete API documentation
- MySQL / MariaDB - Full EXPLAIN analysis
- PostgreSQL - Full EXPLAIN analysis
- H2 - Basic EXPLAIN analysis (great for testing)
All databases work for N+1 and slow query detection.
- Java: 17 or higher
- Spring Boot: 3.x (for starter module)
- Database: Any JDBC-compatible database
git clone https://github.com/query-analyzer/query-analyzer.git
cd query-analyzer
mvn clean install -DskipTests
# Run examples
cd query-analyzer-examples/example-basic
mvn spring-boot:runContributions are welcome. Please open an issue to discuss your idea before submitting a pull request.
MIT License - see LICENSE for details.
Mahmoud Khawaja
Created to help developers identify and fix database performance issues during development, before they impact production systems.

