Skip to content

Commit f04d4f0

Browse files
solracsfCarlSchwan
authored andcommitted
perf(folder): avoid on-disk temp table when sorting folders by group count
Signed-off-by: Git'Fellow <12234510+solracsf@users.noreply.github.com> Signed-off-by: Carl Schwan <carlschwan@kde.org>
1 parent 85afbf0 commit f04d4f0

2 files changed

Lines changed: 48 additions & 4 deletions

File tree

lib/Folder/FolderManager.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,20 @@ public function getAllFoldersWithSize(int $offset = 0, ?int $limit = null, strin
159159
$query->setFirstResult($offset);
160160
$query->setMaxResults($limit);
161161
if ($orderBy === 'groups') {
162-
$query
163-
->leftJoin('f', 'group_folders_groups', 'g', $query->expr()->eq('f.folder_id', 'g.folder_id'))
164-
->groupBy('f.folder_id')
165-
->orderBy($query->func()->count('g.applicable_id'), $order);
162+
// Order by the number of groups/circles applicable to each folder.
163+
//
164+
// We deliberately avoid a "JOIN group_folders_groups + GROUP BY f.folder_id"
165+
// here. Grouping forces the database to materialize an internal temporary
166+
// table, and because the selected `options` column is a LONGTEXT that
167+
// temporary table cannot use the in-memory MEMORY engine, so MariaDB/MySQL
168+
// always spills it to an on-disk (Aria) temp table regardless of
169+
// `tmp_table_size`. A correlated sub-query yields the same ordering without
170+
// grouping the wide result set, so no temporary table is created.
171+
$countSubQuery = $this->connection->getQueryBuilder();
172+
$countSubQuery->select($countSubQuery->func()->count('g.applicable_id'))
173+
->from('group_folders_groups', 'g')
174+
->where($countSubQuery->expr()->eq('g.folder_id', 'f.folder_id'));
175+
$query->orderBy($query->createFunction('(' . $countSubQuery->getSQL() . ')'), $order);
166176
} else {
167177
$query->orderBy($orderBy, $order);
168178
}

tests/Folder/FolderManagerTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use OCA\GroupFolders\Folder\FolderDefinition;
1414
use OCA\GroupFolders\Folder\FolderDefinitionWithPermissions;
1515
use OCA\GroupFolders\Folder\FolderManager;
16+
use OCA\GroupFolders\Folder\FolderWithMappingsAndCache;
1617
use OCA\GroupFolders\Mount\FolderStorageManager;
1718
use OCA\GroupFolders\ResponseDefinitions;
1819
use OCP\Constants;
@@ -661,4 +662,37 @@ public function testCanManageACLCacheInvalidatedOnUserDeletion(): void {
661662
$this->manager->deleteUser('bob');
662663
$this->assertFalse($this->manager->canManageACL($folderId, $user));
663664
}
665+
666+
public function testGetAllFoldersWithSizeOrderedByGroups(): void {
667+
$this->config->expects($this->any())
668+
->method('getSystemValueInt')
669+
->with('groupfolders.quota.default', FileInfo::SPACE_UNLIMITED)
670+
->willReturn(FileInfo::SPACE_UNLIMITED);
671+
672+
// Create folders with a different number of applicable groups each.
673+
$oneGroup = $this->manager->createFolder('one-group');
674+
$threeGroups = $this->manager->createFolder('three-groups');
675+
$twoGroups = $this->manager->createFolder('two-groups');
676+
677+
$this->manager->addApplicableGroup($oneGroup, 'g1');
678+
679+
$this->manager->addApplicableGroup($twoGroups, 'g1');
680+
$this->manager->addApplicableGroup($twoGroups, 'g2');
681+
682+
$this->manager->addApplicableGroup($threeGroups, 'g1');
683+
$this->manager->addApplicableGroup($threeGroups, 'g2');
684+
$this->manager->addApplicableGroup($threeGroups, 'g3');
685+
686+
$ascending = array_map(
687+
fn (FolderWithMappingsAndCache $folder): string => $folder->mountPoint,
688+
array_values($this->manager->getAllFoldersWithSize(0, null, 'groups', 'ASC')),
689+
);
690+
$this->assertEquals(['one-group', 'two-groups', 'three-groups'], $ascending);
691+
692+
$descending = array_map(
693+
fn (FolderWithMappingsAndCache $folder): string => $folder->mountPoint,
694+
array_values($this->manager->getAllFoldersWithSize(0, null, 'groups', 'DESC')),
695+
);
696+
$this->assertEquals(['three-groups', 'two-groups', 'one-group'], $descending);
697+
}
664698
}

0 commit comments

Comments
 (0)