Context は、Oracle Database、Entity Framework 5、LinqToEntities、Database First です。
いくつかの大きなテーブルにページネーションを実装しようとしています.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) )
実際に SQL Developer で時間を費やしたのは Oracle かどうかを確認したところ、そうでした。
次に、実行計画を確認したところ、次のように表示されました。
私が実際に理解しているのは、row_number に対する最初のフィルターには STOPKEY がなく、おそらくサブクエリ全体をフェッチするということだけです。
私が間違っていなければ、リクエストはODT / ODP / ..によって生成されるため、Oracle DB用に最適化する必要があります..(そして私はそれを自分で変更することはできません)
多分私のデータベースモデルは腐っており、インデックスや最適化を追加してよりうまく機能させることができますか?