perf(user_ldap): chunk oracle queries for lower bind cost

Oracle's OCI8 driver binds each named parameter individually via
OCIBindByName, making queries with 65 000 parameters dramatically
slower than on MySQL or PostgreSQL — slow enough to time out in CI
and degrade production LDAP syncs on large installations.

Lower maxSlices to 5 for Oracle (5 000 params/query) via a match
expression alongside the existing SQLite special-case. SQLite and
all other databases are unchanged.

Assisted-by: ClaudeCode:claude-sonnet-4-6
Signed-off-by: Anna Larch <anna@nextcloud.com>
This commit is contained in:
Anna Larch 2026-06-03 10:49:59 +02:00 committed by Anna
parent b6d0e19876
commit 967d8de792
2 changed files with 8 additions and 2 deletions

View file

@ -290,7 +290,13 @@ abstract class AbstractMapping {
public function getListOfIdsByDn(array $fdns): array {
$totalDBParamLimit = 65000;
$sliceSize = 1000;
$maxSlices = $this->dbc->getDatabaseProvider() === IDBConnection::PLATFORM_SQLITE ? 9 : $totalDBParamLimit / $sliceSize;
// SQLite's variable limit is very low; Oracle's OCI8 driver has high per-bind overhead,
// making large parameter lists (65k) extremely slow — use smaller batches for both.
$maxSlices = match ($this->dbc->getDatabaseProvider()) {
IDBConnection::PLATFORM_SQLITE => 9,
IDBConnection::PLATFORM_ORACLE => 5,
default => $totalDBParamLimit / $sliceSize,
};
$results = [];
$slice = 1;

View file

@ -284,7 +284,7 @@ abstract class AbstractMappingTestCase extends \Test\TestCase {
[$mapper,] = $this->initTest();
$listOfDNs = [];
// List size exceeds the implementation's 65000-parameter chunk limit, forcing multiple chunked queries
// List size exceeds any single-query chunk limit (65k for most DBs, 9k for SQLite, 5k for Oracle), forcing multiple chunked queries
for ($i = 0; $i < 66640; $i++) {
$name = 'as_' . $i;
$dn = 'uid=' . $name . ',dc=example,dc=org';