我有 Entity Framework 5 和 Oracle DB 的性能问题。

我有一个简单的 SQL 选择:SELECT * FROM NOTE WHERE NOTENUMBER = '1A23456'NOTENUMBER 包含在名为 NOTE 的表的索引中,但该字段不是主键/唯一键。

  • 当我用 Oracle SQL Developer 执行语句时,结果返回
    很快,查询计划显示正在使用 RANGE SCAN
    应该。
  • 当我使用Entity Framework时,生成的SQL需要很多
    更长(5 秒对 30 毫秒)。
  • 当我使用 Entity Framework 和查询时
    使用 主键字段 (NOTE_KEY),结果返回与 SQL 一样快
    开发商。

  • 我怀疑两件事:
  • EF 和Oracle.DataAccess-provider 不使用可用的非唯一索引存在一些问题。如果我有 Entity Framework 5 的调试符号会有所帮助,但我在任何地方都找不到它们。
  • 性能问题出现在 EF 中,关于闭包和/或我在 EF 中使用通用存储库模式的方式:

    如果我像这样调用我的存储库:var notenumber = "1A23456";var notes = repository.All(n => n.NOTENUMBER == notenumber).ToList();谓词出现在 All 方法中,如下所示:{n => (n.NOTE == value(Tester.Program+<>c__DisplayClass0).notenumber)}EfProf-profiler 将生成的 SQL 跟踪为:
    SELECT "Extent1"."NOTE_KEY" AS "NOTE_KEY","Extent1"."NOTENUMBER" AS "NOTENUMBER","Extent1"."NOTETEXT" AS "NOTETEXT",FROM "NOTE_DBA"."NOTE" "Extent1"WHERE ("Extent1"."NOTENUMBER" = '1PSA0500237500' /* @p__linq__0 */)
    并且查询需要 ~5500ms

    另一方面,如果我像这样调用我的存储库:var notes = repository.All(n => n.NOTENUMBER == "1A23456").ToList();然后谓词如下:{n => (n.NOTENUMBER == "1A23456")}EfProf-profiler 将生成的 SQL 跟踪为:
    SELECT "Extent1"."NOTE_KEY" AS "NOTE_KEY","Extent1"."NOTENUMBER" AS "NOTENUMBER","Extent1"."NOTETEXT" AS "NOTETEXT",FROM "NOTE_DBA"."NOTE" "Extent1"WHERE ('1PSA0500237500' = "Extent1"."NOTENUMBER")
    并且查询需要 ~30ms

    所以唯一的区别是 WHERE 子句中条件的顺序,事实上在后者中似乎没有参数被 EF
  • 替换

    我使用 VS2010 和 .NET4,并引用 EF5 (v4.4.0.0)。
    存储库的 All-method 是:
    public IQueryable<NOTE> All(Expression<Func<NOTE, bool>> predicate = null)
    {
        var setOfNotes = GetDbSet<NOTE>();
        var notesQuery = from note in setOfNotes select note;
        if (predicate != null)
        {
            notesQuery = notesQuery.Where(predicate);
        }
        return notesQuery;
    }
    

    我尝试创建一个 CompiledQuery,我尝试使用 setOfNotes.AsNoTracking() 并尝试针对 .NET 4.5 - 性能没有差异。

    我能够快速获得此特定查询的一种方法是使用 Oracle 的基本数据提供程序 for .NET (ODB.NET) 并手动构建查询,但我不想坚持使用该解决方案。同样,如果我在 where 子句中使用主字段,即使使用 EF 和相同的 All-method,查询也很快。

    所以问题似乎出在 EF 的某个地方。如果我只有 EntityFramework.dll 的符号,我觉得可以找到更多。

    EF 调用谓词的方式会不会有问题?如何在 EF 中替换“@p_linq_0”-参数?

    最佳答案

    我有一个类似的问题。在我的例子中没有使用索引的原因是我从 .NET 传递了一个字符串(unicode)作为参数。这与非 Unicode 数据库字段进行了比较。

    解决方案是在将字符串参数传递到 where 子句之前将其转换为非 unicode:

    using System.Data.Objects;
    
    EntityFunctions.AsNonUnicode( myUnicodeParam)
    

    关于performance - Entity Framework 5 和 Oracle : Expression with closure affecting performance when querying against a non-unique indexed field,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12177322/

    10-09 01:50