【发布时间】:2015-09-18 05:25:29
【问题描述】:
我在 MVC 4 网站中使用 Entity Framework 5.0.0。
网站的一部分允许用户在数据库中搜索记录。搜索最多可以包含 10 个搜索条件,这些条件可能涉及(生成 where 子句)4-5 个表并从 14 个表返回数据。
搜索页面提供了许多可供搜索的字段:关键字、标题、日期等。
搜索功能允许搜索词的“或”或“与”组合。 例如,可以要求 Title AND Date 匹配,或者 Title OR Date 匹配。
查询看起来类似于:
Dim searchQuery As IQueryable(Of MainTableClass) = Nothing
Dim query As IQueryable(Of MainTableClass) = Nothing
Dim queries As List(Of IQueryable(Of MainTableClass)) = New List(Of IQueryable(Of MainTableClass))
Using database As DataContext = new DataContext
searchQuery = ( From x In database.MainTableClasses. _
Include("Secondary.Third.Fourth"). _
Include("Secondary.Fifth.Sixth"). _
Include("Eighth"). _
Include("Nine.Ten.Eleven.Twelve"). _
Include("Thirteen.Fourteen")
Select x)
' Some things here to limit the initial set that searchQuery returns
' eg: searchQuery = searchQuery.Where(Function(m) m...blah blah)
If Not String.IsNullOrEmpty(model.Title) Then
query = (From x In database.MainTableClasses Where x.Secondary.Title = model.Title Select x)
queries.Add(query)
End If
If Not Nothing Is model.Date Then
query = ( From x In database
Where x.Nine.Any(Function(a) model.Date < a.Value) )
queries.Add(query)
End If
'
' Now to combine the results
'
For Each item As IQueryable(Of MainTableClass) In queries
Select Case model.SearchType
Case SearchType.OR ' Or the search terms
searchQuery = searchQuery.Union(item)
Case Else ' And the search terms
searchQuery = searchQuery.Intersect(item)
End Select
Next
'
' Run the query
'
results = searchQuery.ToList
End Using
问题在于,Linq 将实际查询转换为 5700 行 SQL,并且在 Azure 最大的 SQL 数据库产品上运行需要 9 秒以上。完全不能接受。我可以在不到 30 行的时间内用 SQL 手动编写主要搜索查询。
那么,我能做些什么来重构这个查询,让它运行得更快呢? EF/Linq 不是正确的工具吗?我在这里做错了什么吗?
【问题讨论】:
-
这不是适合这项工作的工具。您最好在某个字段上创建一个全文索引,该字段将包含您需要搜索的连接数据,然后使用entityframework.info/Home/FullTextSearch 中描述的解决方案。否则,您将不得不选择 Lucene / ElasticSearch 等。
-
这是一个完全不可接受的解决方案。如果我要手动编写 SQL,它会很快工作。这些表中的数据不断变化 - 创建和维护一个将搜索数据连接在一起的字段是不可能的。
-
您能解释一下手工生成的查询和 Linq 生成的查询之间的区别吗?在我看来,您可以避免使用许多
Include语句,并可能稍后重新加载引用。这可以是一个开始.. -
主要区别在于 LINQ 查询将近 5700 行,而手写查询大约 10 行。稍后我会写出我的解决方案。
标签: sql-server performance entity-framework linq-to-entities entity-framework-5