LINQ 需要 40 秒才能结束查询 - 性能
LINQ takes 40s to end query - Performance
我正在调用本地网络之外的外部数据库,但是查询需要 40 秒才能结束..
我正在使用 edmx 拨打电话。
String Example = "Example";
var Result = EDMXEntity.Entities
.Where(
x =>
(
x.Name.ToString().ToLower().Contains(Example.ToLower())
))
.Take(50)
.ToList();
感谢 Szer 的当前代码:
var Result = EDMXEntity.Entities.Where(x => SqlFunctions.PatIndex(x.Name.ToString().ToLower(), Example.ToLower()) > 0).Take(50).ToList();
sql server management studio does it in less than a second
这很可能是由于缓存的查询执行计划不正确造成的,如 here, here and here 所述。
人们发现 运行 针对 SQL 服务器的以下命令为他们解决了这个问题。 (可能真的只需要第二个命令。)
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
字符串比较的最佳选择是使用大小写不等式,这样您就不必处理转换字符串的问题。在那种情况下,我认为名称上的 .ToString 并不是必需的(话又说回来,我不确定它是如何存储的,所以可能需要它)。还有名称,您可以尝试使用相等性或至少
最后,您可以尝试将其拆分为一个 Queryable 对象,然后 运行 以这种方式进行查询。这样,您可以减少用于查询本身的资源数量。
编辑
由于不希望检查整个字符串,您可以改用 IndexOf 以避免使用完整的字符串
查看以下内容:
String Example = "Example";
var EDMXEntity = new List<String>();
var Query = EDMXEntity.Entities.AsQueryable();
var Result = Query
.Where(
x =>
(
x.Name.ToString().ToLower().Contains(Example.ToLower())
))
.Take(50)
.ToList();
我上面评论的迟到答案:
问题是您正在将所有实体从数据库加载到内存并在您的计算机上进行过滤。您应该在数据库引擎的帮助下过滤您的查询。
为此,您应该使用 SqlFunctions,它由 LINQ SQL 提供程序映射到直接 T-SQL 代码。
在您的情况下,您可以将 string.Contains()
替换为 SqlFunctions.PatIndex
这几乎是相同的(它 returns int
而不是 bool
)
像这样:
var result = EDMXEntity.Entities
.Where(x => SqlFunctions.PatIndex(
stringPattern: x.Name.ToString().ToLower(),
target: Example.ToLower()) > 0)
.Take(50)
.ToList();
我正在调用本地网络之外的外部数据库,但是查询需要 40 秒才能结束..
我正在使用 edmx 拨打电话。
String Example = "Example";
var Result = EDMXEntity.Entities
.Where(
x =>
(
x.Name.ToString().ToLower().Contains(Example.ToLower())
))
.Take(50)
.ToList();
感谢 Szer 的当前代码:
var Result = EDMXEntity.Entities.Where(x => SqlFunctions.PatIndex(x.Name.ToString().ToLower(), Example.ToLower()) > 0).Take(50).ToList();
sql server management studio does it in less than a second
这很可能是由于缓存的查询执行计划不正确造成的,如 here, here and here 所述。
人们发现 运行 针对 SQL 服务器的以下命令为他们解决了这个问题。 (可能真的只需要第二个命令。)
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
字符串比较的最佳选择是使用大小写不等式,这样您就不必处理转换字符串的问题。在那种情况下,我认为名称上的 .ToString 并不是必需的(话又说回来,我不确定它是如何存储的,所以可能需要它)。还有名称,您可以尝试使用相等性或至少
最后,您可以尝试将其拆分为一个 Queryable 对象,然后 运行 以这种方式进行查询。这样,您可以减少用于查询本身的资源数量。
编辑
由于不希望检查整个字符串,您可以改用 IndexOf 以避免使用完整的字符串
查看以下内容:
String Example = "Example";
var EDMXEntity = new List<String>();
var Query = EDMXEntity.Entities.AsQueryable();
var Result = Query
.Where(
x =>
(
x.Name.ToString().ToLower().Contains(Example.ToLower())
))
.Take(50)
.ToList();
我上面评论的迟到答案:
问题是您正在将所有实体从数据库加载到内存并在您的计算机上进行过滤。您应该在数据库引擎的帮助下过滤您的查询。
为此,您应该使用 SqlFunctions,它由 LINQ SQL 提供程序映射到直接 T-SQL 代码。
在您的情况下,您可以将 string.Contains()
替换为 SqlFunctions.PatIndex
这几乎是相同的(它 returns int
而不是 bool
)
像这样:
var result = EDMXEntity.Entities
.Where(x => SqlFunctions.PatIndex(
stringPattern: x.Name.ToString().ToLower(),
target: Example.ToLower()) > 0)
.Take(50)
.ToList();