Как улучшить производительность запросов Linq относительно Trim()
Таблицы нашей компании были созданы с полями с пробелами.
У меня нет доступа / разрешений для внесения изменений в БД.
Тем не менее, я заметил, что когда я создаю запросы LINQ с использованием функции Trim(), производительность значительно снижается.
Простой запрос показывает, что производительность снижается:
Companies
.Where(c => c.CompanyName.Equals("Apple"))
.Select(c => new {
Tick = c.Ticker.Trim(),
Address = c.Address.Trim()
});
Есть ли способ изменить запрос, чтобы не было потери производительности?
Или все это зависит только от моего администратора?
3 ответа
Быстрое решение состоит в том, чтобы добавить название вашей компании, прежде чем отправлять его на запрос. Например, если столбец char(50)
:
var paddedName = "Apple".PadRight(50);
var result = Companies
.Where(c => c.CompanyName.Equals(paddedName))
.Select(c => new {
Tick = c.Ticker.Trim(),
Address = c.Address.Trim()
});
Тем не менее, вы должны рассмотреть возможность исправления базы данных, чтобы избежать дальнейших проблем.
Помимо Entity Framework, linq-to-sql может иногда переключаться на linq-to-objects под капотом, когда сталкивается с вызовами методов, которые не могут быть преобразованы в SQL. Так что если вы делаете
....
.Select(c => new {
Tick = c.Ticker.TrimEnd().TrimStart(),
Address = c.Address.TrimEnd().TrimStart()
вы заметите, что сгенерированный SQL больше не содержит LTRIM(RTRIM())
, но только имя поля и то, что обрезки выполняются в памяти клиента. Видимо, как-то LTRIM(RTRIM())
вызывает менее эффективный план запроса (на удивление).
Возможно только TrimEnd()
Достаточно, если нет пробелов.
Кроме того, я полностью согласен с pswg, что вы должны стараться изо всех сил пытаться очистить базу данных вместо исправления неверных данных в запросах. Если вы не можете сделать эту работу, найдите подходящих людей и скрутите их руки.
Я не проверял производительность, если мы используем оператор "Мне нравится" для выполнения фильтра первого раунда и устанавливаем его.ToList(), во втором раунде только внутренняя проверка выполняется без вызова базы данных.
var result = (Companies
.Where(c => c.CompanyName.StartsWith("Apple"))
.Select(c => new
{
Tick = c.Ticker.Trim(),
Address = c.Address.Trim()
})).ToList();
var result1=result
.Where(c=>c.CompanyName.Trim().Equals("Apple"))
.Select(c => c);