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花了一些时间,而且确实是。
然后我检查了执行计划,它出现了:
我真正理解的是,对于row_number上的第一个过滤器没有STOPKEY,它可能会获取整个子查询。
我真的不知道在哪里看,如果我没有弄错,请求是由ODT / ODP / ..生成的,因此,应针对Oracle DB进行优化..(和我不能自己改变)
也许我的数据库模型已经烂了,我可以添加更多索引或优化以使其更好地工作?
答案 0 :(得分:2)
你看到所有那些独特的SCAN子查询?这对每一张桌子都是独一无二的。
您应该与T1成为父对象,并且您需要在查询中与T1上的索引ID主键列具有FOREIGN KEY
关系的任何表。
然后您可以使用Join
代替Include
,并且不需要子查询。