Joe*_*nos 1 join sql-server entity-framework
我有一种感觉,答案是“这取决于……”,但我想知道是否有具体的答案。
在实体框架中,您使用 C# 代码构建查询,框架将转换为 SQL 并发送到服务器以下拉数据。假设我想从三个表中检索一条记录。我至少有三个选择:
使用直接 SQL(手动 ADO.NET),SELECT
在同一命令中发送三个语句,并使用 DataReader 一次映射一个结果集。从数据库的角度来看,这显然是最好的方法,但它是最有效的方法,因为我无法使用实体框架方法。
从实体框架发送三个单独的命令 - 这需要到数据库服务器的三个往返:
Person person1 = context.Persons.First(p => p.PersonID == 1);
Car car1 = context.Cars.First(c => c.CarID == 1);
House house1 = context.Houses.First(h => h.HouseID == 1);
// translates to the following SQL, one roundtrip at a time:
SELECT TOP(1) [p].[PersonID], [p].[PersonName] FROM [Person] AS [p] WHERE [p].[PersonID] = 1
SELECT TOP(1) [c].[CarID], [c].[CarName] FROM [Car] AS [c] WHERE [c].[CarID] = 1
SELECT TOP(1) [h].[HouseID], [h].[HouseName] FROM [House] AS [h] WHERE [h].[HouseID] = 1
Run Code Online (Sandbox Code Playgroud)
var query = (from p in context.Persons.Where(p => p.PersonID == 1)
from c in context.Cars.Where(c => c.CarID == 1)
from h in context.Houses.Where(h => h.HouseID == 1)
select new { p, c, h }).First();
Person person2 = query.p;
Car car2 = query.c;
House house2 = query.h;
// which makes the following SQL:
SELECT TOP(1) [p].[PersonID], [p].[PersonName], [t].[CarID], [t].[CarName], [t0].[HouseID], [t0].[HouseName]
FROM [Person] AS [p]
CROSS JOIN (
SELECT [c].[CarID], [c].[CarName] FROM [Car] AS [c] WHERE [c].[CarID] = 1
) AS [t]
CROSS JOIN (
SELECT [h].[HouseID], [h].[HouseName] FROM [House] AS [h] WHERE [h].[HouseID] = 1
) AS [t0]
WHERE [p].[PersonID] = 1
Run Code Online (Sandbox Code Playgroud)
交叉连接最终只会使结果变平,因为每个表只返回一条记录,并且正确的索引会触发,所以我认为数据库会对此感到满意 - 往返次数更少,但返回的数据量相同。
#3 中的代码更丑陋,但这不是我要问的 - 我只是从性能角度询问。第三个示例中的交叉连接是否会导致任何潜在问题?也许使用单个命令不需要锁定问题或额外的 CPU 或内存?
值得一提的是,这两个查询可能不会返回相同的结果。按 ID 进行的三个单独查询将始终返回您的三行。在该CROSS JOIN
方法中,如果PersonID = 1
不存在,则不会返回其他两个实体的信息。因此,您的应用程序必须确定所有这些 ID 都存在,否则您可能会得到意想不到的结果。
只要您的每个表在 ID 列上都有一个唯一的聚集索引(或主键)(或覆盖的非聚集索引 - 重点是寻找正确的行是可能的),两种方法之间的性能差异,从SQL Server 的角度来看,是可以忽略不计的。
这两种方法都会导致对聚集索引进行 3 次搜索。既不应该并行,也不应该需要排序,并且交叉连接应该使用嵌套循环 - 因此在任何一种情况下都不需要内存授权。
三批方法很明显:
该CROSS JOIN
方法如下所示:
按照这个计划的运作方式,每个搜索操作符最多执行一次:
PK_House
返回一行给嵌套循环运算符PK_Person
,将一行返回给同一个 Nested Loops 运算符PK_Car
,将一行返回给第二个嵌套循环运算符如果您不想在整个应用程序中编写交叉联接(可能会使其他开发人员感到困惑),您可以通过使用提供“未来”查询的实体框架扩展之一来避免多次往返的开销。这些使您可以将多个查询排队,当需要其中任何一个的结果时,它们都将被批量发送和解决。
一个这样的扩展是Entity Framework Plus -query-future
。
归档时间: |
|
查看次数: |
61 次 |
最近记录: |