为什么LinqToEntities跳过/采取oracle实现这么慢

时间:2014-01-22 12:34:07

标签: c# sql oracle entity-framework skip-take

Context是Oracle数据库,实体框架5,LinqToEntities,数据库优先。

我正在尝试在一些大表上实现分页,我的linqToEntities查询看起来像这样:

context.MyDbSet
    .Include("T2")
    .Include("T3")
    .Include("T4")
    .Include("T5")
    .Include("T6")
    .Where(o => o.T3 != null)
    .OrderBy(o => o.Id)
    .Skip(16300)
    .Take(50);

事实上,根据我想跳过多少条记录(0或16300),它会从0.08秒变为10.7秒。

这对我来说似乎很奇怪所以我检查了生成的SQL,这是它的样子:

SELECT * 
FROM ( 
SELECT 
[...]
FROM ( SELECT [...] row_number() OVER (ORDER BY "Extent1"."Id" ASC) AS "row_number"
    FROM      T1 "Extent1"
    LEFT OUTER JOIN T2 "Extent2" ON [...]
    LEFT OUTER JOIN T3 "Extent3" ON [...]
    LEFT OUTER JOIN T4 "Extent4" ON [...]
    LEFT OUTER JOIN T5 "Extent5" ON [...]
    LEFT OUTER JOIN T6 "Extent6" ON [...]
    WHERE ("Extent1"."SomeId" IS NOT NULL)
)  "Filter1"
WHERE ("Filter1"."row_number" > 16300)
ORDER BY "Filter1"."Id" ASC
)
WHERE (ROWNUM <= (50) )

我检查过是否确实是Oracle通过SQL Developper花了一些时间,而且确实是。

然后我检查了执行计划,它出现了:

Execution Plan

我真正理解的是,对于row_number上的第一个过滤器没有STOPKEY,它可能会获取整个子查询。

我真的不知道在哪里看,如果我没有弄错,请求是由ODT / ODP / ..生成的,因此,应针对Oracle DB进行优化..(和我不能自己改变)

也许我的数据库模型已经烂了,我可以添加更多索引或优化以使其更好地工作?

1 个答案:

答案 0 :(得分:2)

你看到所有那些独特的SCAN子查询?这对每一张桌子都是独一无二的。

您应该与T1成为父对象,并且您需要在查询中与T1上的索引ID主键列具有FOREIGN KEY关系的任何表。

然后您可以使用Join代替Include,并且不需要子查询。

相关问题