This project focused on improving omegaUp's database performance and detecting inefficient SQL queries before they reach production.
The original proposal had three deliverables:
general_log and EXPLAIN.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.
| 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.
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.
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.
EXPLAIN and the relevant existing tests.stuff/process_mysql_explain_logs_test.py now has 28
focused tests for normalization, Query Family, stable identities,
deduplication, allowlist validation, comparison, and exit codes.general_log cleanup change passes Bash syntax
validation, git diff --check, and omegaUp's official lint
command.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.
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.
EXPLAIN
rows. Treating only the normalized SQL text as its identity can silently
discard a problem reported for a second table.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.
The main areas changed or studied during this project are:
frontend/database/ — database schema and index
migrations.frontend/server/src/DAO/ — SQL queries used by
omegaUp's data-access layer.stuff/process_mysql_explain_logs.py — EXPLAIN analysis
and CSV generation.stuff/process_mysql_explain_logs_test.py — focused
tests for detector logic.stuff/mysql_types.sh — execution flow that captures and
processes queries.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.
Thank you to my omegaUp mentors and maintainers for their guidance, reviews, and technical feedback throughout GSoC 2026.