MDL-68183 auth: Fix the performance of get_complete_user_data search

When searching for the user by a case-insensitive field (email address
is the only one supported now), the performance may be very poor as the
DB cannot use the index due to the LOWER() operation and the full
sequential scan of all the user records is performed. On some DBs such
as MySQL, this can be significantly improved by pre-filtering the users
with accent-insensitive search.

So we first perform accent-insensitive search for potential candidates
in a subselect, which can use the index. Only then we perform the
additional accent-sensitive search on this limited set or records.
This commit is contained in:
David Mudrák
2020-03-17 14:52:25 +01:00
parent 39901e1577
commit e8ae8a8a76
+9 -1
View File
@@ -4846,11 +4846,15 @@ function get_complete_user_data($field, $value, $mnethostid = null, $throwexcept
// Build the WHERE clause for an SQL query.
$params = array('fieldval' => $value);
// Do a case-insensitive query, if necessary.
// Do a case-insensitive query, if necessary. These are generally very expensive. The performance can be improved on some DBs
// such as MySQL by pre-filtering users with accent-insensitive subselect.
if (in_array($field, $caseinsensitivefields)) {
$fieldselect = $DB->sql_equal($field, ':fieldval', false);
$idsubselect = $DB->sql_equal($field, ':fieldval2', false, false);
$params['fieldval2'] = $value;
} else {
$fieldselect = "$field = :fieldval";
$idsubselect = '';
}
$constraints = "$fieldselect AND deleted <> 1";
@@ -4867,6 +4871,10 @@ function get_complete_user_data($field, $value, $mnethostid = null, $throwexcept
$constraints .= " AND mnethostid = :mnethostid";
}
if ($idsubselect) {
$constraints .= " AND id IN (SELECT id FROM {user} WHERE {$idsubselect})";
}
// Get all the basic user data.
try {
// Make sure that there's only a single record that matches our query.