From 53374c26afb346ec78ffe3a3cefb74492701e5c5 Mon Sep 17 00:00:00 2001 From: Phillipxh <150742483+Phillipxh@users.noreply.github.com> Date: Fri, 30 Oct 2026 22:35:51 +0100 Subject: [PATCH] fix(database): drop the join-without-index rules Select_full_join and Join_without_index_rate cannot be acted on by an admin: - The queries behind the counters are not logged by default, so there is no way to tell which query did the join. - Most of them are Nextcloud's own: the core setup checks introspect the schema through information_schema, whose tables have no indexes, so every visit of Administration -> Overview adds to Select_full_join. - Even if the query were known, adding an index by hand would make the schema check report it as unexpected. Remove both rules, as suggested in review. Fixes #1245 Assisted-by: ClaudeCode:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_019TNUHUT6jaQ3BHvjvdf4Ny Signed-off-by: Phillipxh <150742483+Phillipxh@users.noreply.github.com> --- lib/Database/Advisor.php | 2 -- lib/Database/RuleSet/Mysql.php | 29 ----------------------------- tests/lib/Database/AdvisorTest.php | 16 ---------------- 3 files changed, 47 deletions(-) diff --git a/lib/Database/Advisor.php b/lib/Database/Advisor.php index f905a9d5..f33f655c 100644 --- a/lib/Database/Advisor.php +++ b/lib/Database/Advisor.php @@ -49,7 +49,6 @@ class Advisor { 'Aborted_connects', 'Thread_cache_hit_rate', 'Slow_query_ratio', - 'Select_full_join', 'Sort_merge_passes', 'Created_tmp_disk_tables', 'Innodb_buffer_pool_hit_rate', @@ -61,7 +60,6 @@ class Advisor { 'Slow_query_rate', 'Sort_rows', 'Sort_merge_passes_rate', - 'Join_without_index_rate', 'Handler_read_first_rate', 'Handler_read_rnd_rate', 'Handler_read_rnd_next_rate', diff --git a/lib/Database/RuleSet/Mysql.php b/lib/Database/RuleSet/Mysql.php index 77e3bcfb..6848f755 100644 --- a/lib/Database/RuleSet/Mysql.php +++ b/lib/Database/RuleSet/Mysql.php @@ -177,20 +177,6 @@ private function build(): array { requires: ['Slow_queries', 'Questions'], ); - $rules[] = new Rule( - id: 'Select_full_join', - name: 'Joins without indexes', - category: 'Performance', - severity: Rule::SEVERITY_WARNING, - formula: 'Select_full_join / Questions * 100', - test: 'value > 0.05', - issue: 'Some joins are scanning entire tables because no usable index exists on the join column.', - recommendation: 'Identify the offending queries (set log_queries_not_using_indexes) and add the missing indexes.', - justification: '%s%% of queries did a full join without an index.', - justificationFormula: 'value', - requires: ['Select_full_join', 'Questions'], - ); - $rules[] = new Rule( id: 'Sort_merge_passes', name: 'Sort buffer passes', @@ -488,21 +474,6 @@ private function build(): array { ); // Performance / joins + scans (rate-based companions to existing absolute checks) - $rules[] = new Rule( - // upstream id: "Rate of joins without indexes" - id: 'Join_without_index_rate', - name: 'Join-without-index rate', - category: 'Performance', - severity: Rule::SEVERITY_NOTICE, - formula: '(Select_range_check + Select_scan + Select_full_join) / Uptime', - test: 'value * 60 * 60 > 1', - issue: 'Many SELECTs are doing full table scans or joins without indexes.', - recommendation: 'Add indexes for the columns used in JOIN conditions and WHERE filters.', - justification: 'Index-less join+scan rate: %s per hour; aim for less than 1.', - justificationFormula: 'round(value * 3600, 2)', - requires: ['Select_range_check', 'Select_scan', 'Select_full_join', 'Uptime'], - ); - $rules[] = new Rule( // upstream id: "Rate of reading first index entry" id: 'Handler_read_first_rate', diff --git a/tests/lib/Database/AdvisorTest.php b/tests/lib/Database/AdvisorTest.php index d48c51b2..300e3a89 100644 --- a/tests/lib/Database/AdvisorTest.php +++ b/tests/lib/Database/AdvisorTest.php @@ -11,7 +11,6 @@ use OCA\ServerInfo\Database\Advisor; use OCA\ServerInfo\Database\ExpressionEvaluator; -use OCA\ServerInfo\Database\Rule; use OCA\ServerInfo\Database\RuleResult; use OCA\ServerInfo\Database\RuleSet\Mysql; use OCA\ServerInfo\Database\Snapshot; @@ -135,19 +134,4 @@ public function testReplicaLagPassesOnRunningReplica(): void { $this->assertSame(RuleResult::STATUS_OK, $result->status); } - - /** - * Select_scan alone exceeds one per hour on any active Nextcloud, so the - * rule is a hint rather than a warning. - */ - public function testJoinWithoutIndexRateIsANotice(): void { - $result = $this->resultFor('Join_without_index_rate', [ - 'Select_range_check' => 0, - 'Select_scan' => 50000, - 'Select_full_join' => 0, - ]); - - $this->assertSame(RuleResult::STATUS_FAIL, $result->status); - $this->assertSame(Rule::SEVERITY_NOTICE, $result->rule->severity); - } }