GSoC 2026 Final Work Product — Query Optimization and Performance Benchmarking

Project information

Project overview

This project focused on improving omegaUp's database performance and detecting inefficient SQL queries before they reach production.

The original proposal had three deliverables:

  1. Find and optimize inefficient queries using MySQL general_log and EXPLAIN.
  2. Turn the EXPLAIN report into a CI check with a versioned allowlist.
  3. Add execution-time benchmarks for critical queries.

After reviewing the timeline with my mentors, we decided to focus on the first two parts. Performance benchmarking was left for later because it did not fit within the available time.

Most of my work went into query optimization, with eleven pull requests merged. The EXPLAIN work now includes query normalization, stable identities, Query Family grouping, reliable general_log cleanup, a versioned allowlist, and an initial reviewed baseline. The final comparison and CI failure changes have also been submitted and are under review.

Summary of results

Deliverable Final status
Optimize inefficient queries Completed for the selected queries: 11 merged PRs covering courses, identities, problems, contests, submissions, groups, and assignments
EXPLAIN regression check Under review: normalization, stable identity, Query Family, general_log cleanup, the allowlist format, and its initial baseline are merged. Comparison and CI failure are open pull requests
Performance benchmarks Deferred: the dataset, timing script, thresholds, and CI job remain future work

Across the project and the follow-up work after the final submission, I opened 19 pull requests: 17 were merged and 2 are currently under review. I also created 22 issues to document the problems, proposed changes, and follow-up work.

Work completed

1. SQL query optimizations

For each optimization, I located the inefficient query, reviewed its execution plan, changed its indexes or SQL structure, and checked that its behavior did not change.

Pull request Related issue(s) Result Status
#9912 — Add an index for course name searches #8270 Replaced the previous course-name search strategy and added an index for the lookup Merged
#9915 — Optimize username and name search in Identities #9907 Introduced FULLTEXT search with the ngram parser for identity searches Merged
#9935 — Refine student progress query #9929 Removed a subquery pattern that prevented MySQL from using the available indexes efficiently Merged
#9963 — Optimize contest query with STRAIGHT_JOIN #9959 Changed the join order so MySQL could avoid a full scan of Contests Merged
#10028 — Optimize problem searches with FULLTEXT ngram #9974, #9976 Replaced wildcard searches with MATCH ... AGAINST for problem title and alias searches Merged
#10067 — Remove the index hint from getLatestSubmissions #10054 Allowed MySQL to select a more suitable index for recent submissions Merged
#10080 — Optimize the administered courses list #10056 Reworked permission paths to avoid the previous LEFT JOIN and OR pattern Merged
#10081 — Optimize the administered groups list #10057 Reworked the query used to list groups administered by a user Merged
#10085 — Optimize administered problem listing and count #10058 Improved both the listing and count queries for administered problems Merged
#10091 — Optimize assignment max_points updates #10059 Limited the points calculation to the assignment being updated Merged
#10092 — Optimize participant counts in contest lists #10055 Avoided calculating participant counts for every contest before filtering the requested list Merged

The investigation for the proposed composite index on Assignments was also tracked in #9927. The issue is closed and has no separate authored PR in this work-product list.

2. Foundations for SQL regression detection

The repository already captured SQL statements from general_log, ran EXPLAIN, and generated inefficient_queries.csv. The output was not stable enough for an allowlist, and new inefficient queries did not make CI fail.

I completed or submitted the following foundation work:

Pull request / issue Change Status
PR #10105 / Issue #10103 Made query normalization deterministic for repeated spaces, tabs, and line breaks; added focused Python tests Merged
PR #10114 / Issue #10104 Changed deduplication from query-only identity to (normalized query, table), preserving separate EXPLAIN findings for different tables Merged
PR #10120 / Issue #10113 Groups variable IN lists under a common Query Family for easier CSV review, without using the family for deduplication Merged
PR #10121 / Issue #10107 Guarantees that MySQL general_log is disabled when the test script exits early because of a failure Merged
PR #10126 / Issue #10106 Defines and validates the YAML format used to keep known inefficient query-table pairs in a versioned allowlist Merged
PR #10129 / Issue #10108 Adds the initial reviewed allowlist generated from CI results on an updated main Merged
PR #10134 / Issue #10109 Compares detected findings with the allowlist and classifies them as known, new, or not detected in the current run Under review
PR #10135 / Issue #10110 Makes CI fail after reporting every new inefficient query and keeps the CSV available for investigation Under review; depends on PR #10134

The intended data flow is:

PHP tests
   ↓
MySQL general_log
   ↓
EXPLAIN for captured queries
   ↓
Normalization + stable (query, table) identity
   ↓
Known allowlist entry ── yes ──> CI passes
                     └── no  ──> new regression; CI fails

Query Family adds a broader representation to make related CSV rows easier to inspect:

IN (?)
IN (?, ?)
IN (?, ?, ?)
        ↓
Query Family: IN (?)

This is only used for grouping and sorting. The identity remains (Normalized Query, Table) so different EXPLAIN results are not hidden.

Testing and validation

Current state and remaining work

I divided the remaining EXPLAIN work into small public issues and continued implementing them after the final submission.

These changes need to be integrated in order. The comparison PR is currently ready for review, while the CI failure PR depends on it.

Order Issue Purpose Current state
1 #10104 Stable identity and correct deduplication PR #10114 merged
2 #10113 Query Family grouping in the CSV PR #10120 merged
3 #10106 Define and validate the allowlist format PR #10126 merged
4 #10107 Guarantee cleanup of general_log on success and failure PR #10121 merged
5 #10108 Generate the initial allowlist from an updated main PR #10129 merged
6 #10109 Compare detected findings with the allowlist PR #10134 under review; checks passing
7 #10110 Make CI fail for new inefficient queries PR #10135 under review; SQL validation passing
8 #10111 Cover special cases and EXPLAIN errors Planned
9 #10112 Document how to use and maintain the allowlist Planned

Performance benchmarking remains a later phase. It would add a larger synthetic dataset, repeated query execution, average/p95/p99 measurements, reviewed thresholds, and a separate CI job.

Differences from the original proposal

The proposal originally divided the effort between query optimization (40%), the EXPLAIN check (30%), and performance benchmarks (30%). In practice, investigating and validating production queries took more time than expected. After discussing it with my mentors, we prioritized the first two parts.

This resulted in eleven merged query optimizations and a nearly complete EXPLAIN regression check. The allowlist and initial baseline are merged, while the final comparison and CI failure mechanism are under review. Performance benchmarking was deferred. The tables above show which work is merged, under review, or still planned.

Challenges and lessons learned

Continuing work after the final submission

This report keeps the original final-submission date of August 24, 2026. After that submission, I completed the allowlist format and baseline, then submitted the comparison and CI failure changes. The remaining work is to cover special EXPLAIN cases and document how to review failures and maintain the allowlist.

Relevant code

The main areas changed or studied during this project are:

All code submitted as project work is linked through the pull-request tables above. Work completed before the GSoC coding period, including proposal references #9648, #9666, and #9674, is context only and is not counted among the results reported here.

Acknowledgements

Thank you to my omegaUp mentors and maintainers for their guidance, reviews, and technical feedback throughout GSoC 2026.