perf(core): avoid rewriting all NULL-ecosystem rows during database maintenance - #8736
perf(core): avoid rewriting all NULL-ecosystem rows during database maintenance#8736Turbots wants to merge 1 commit into
Conversation
…aintenance The UPDATE_ECOSYSTEM statement updated every cpeEntry row with a NULL ecosystem on every maintenance run. Rows whose vendor/product has no usable cpeEcosystemCache entry (unknown or 'MULTIPLE') can never receive a value, yet the statement rewrote them with NULL on each run - roughly 145k wasted row writes per update on H2. - Add an EXISTS guard to UPDATE_ECOSYSTEM so only rows that will actually receive an ecosystem value are touched. - Rewrite the H2 CLEANUP_ORPHANS as NOT EXISTS so it probes the idxSoftwareCpe index instead of materializing a full LEFT JOIN. - Log the elapsed time of each maintenance statement. Measured on a full NVD rebuild (H2): database maintenance dropped from 189,482 ms to 1,732 ms. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Hello, first time contributor here! Our team at KOR Financial (https://www.korfinancial.com) are actively using this plugin on a daily basis for every build on Let me know if you want me to adjust something in the commit. Also, not sure whether you prefer (or dislike) the Claude co-author in the commit message. Let me know and I can adjust. |
|
@Turbots I had Claude take a look and... Gaps and improvements
None of these should block the merge — item 1 is the only one I'd ask the author to change in-PR; the rest are follow-ups. |
@Turbots I do prefer Claude to be there |
There was a problem hiding this comment.
Pull request overview
Optimizes H2 database maintenance and adds statement-level timing.
Changes:
- Avoids no-op ecosystem updates.
- Uses indexed orphan checks.
- Adds maintenance timing logs.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
dbStatements.properties |
Guards ecosystem updates with EXISTS. |
dbStatements_h2.properties |
Replaces orphan cleanup with NOT EXISTS. |
CveDB.java |
Records maintenance statement durations. |
Suppressed comments (2)
core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java:1797
- Orphan cleanup commonly has nothing to delete, but the query can still regress and become slow. Because this log remains behind
count > 0, those executions have no per-statement duration; log the zero count and timing as well.
LOGGER.info("Cleaned up {} orphaned NVD records ({} ms)", count,
System.currentTimeMillis() - orphanStart);
core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java:1789
- This timing also disappears when the statement changes zero rows, so a costly no-op
UPDATE_ECOSYSTEM2cannot be identified from the new per-statement logs. Log its count and elapsed time unconditionally.
LOGGER.info("Removed the CPE ecosystem on {} NVD records ({} ms)", count,
System.currentTimeMillis() - ecosystemStart);
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| LOGGER.info("Updated the CPE ecosystem on {} NVD records ({} ms)", count, | ||
| System.currentTimeMillis() - ecosystemStart); |
Summary
Database maintenance after an NVD update rewrites every
cpeEntryrow with a NULL ecosystem on every run. The'MULTIPLE'filter ofUPDATE_ECOSYSTEMsits inside the correlated subquery, while the outerWHEREclause only checkse.ecosystem IS NULL. Rows whose vendor/product pair is unknown or mapped toMULTIPLEcan never receive a value, yet H2 rewrites them with NULL-to-NULL updates each time — ~145k wasted row writes per maintenance run on a typical database.Since the insert path (
H2Functions.insertSoftware/CveDB.updateVulnerabilityInsertSoftware) already sets the ecosystem from theCpeEcosystemCacheat insert time, the repair pass has very little real work to do.Changes
dbStatements.properties: add anEXISTSguard toUPDATE_ECOSYSTEMso only rows that will actually receive an ecosystem value are updated (mirrors the approach already used by the MS SQL Server variant).dbStatements_h2.properties: rewriteCLEANUP_ORPHANSasNOT EXISTSso H2 probes theidxSoftwareCpeindex per row instead of materializing a fullLEFT JOINofcpeEntryagainstsoftwareinside anINsubquery.CveDB.cleanupDatabase(): log the elapsed time of each maintenance statement to make future regressions visible.Measurements
Full NVD cache rebuild (data feed mirror, H2 database, all years + modified):
Verification
MULTIPLErows NULL, and the orphan delete removes exactly the orphaned rows.mvn -pl maven -am installbuilds successfully; ran a full rebuild plus scan through the built plugin against a real project.🤖 Generated with Claude Code