简体   繁体   English

使用Entity Framework进行Oracle查询的速度非常慢

[英]Oracle query using Entity Framework is ridiculously slow

Here is my setup: 这是我的设置:

  • Compiling at .NET 4.0 (I can't go any higher than this) 在.NET 4.0上编译(我不能高于此)
  • Using EntityFramework against Oracle 11gR2 database 对Oracle 11gR2数据库使用EntityFramework
  • Using ODP.NET 11.2.0.3.20 使用ODP.NET 11.2.0.3.20
  • Using Visual Studio 2012 Ultimate and Oracle Developer Tools for Visual Studio 11.2.0.3.20 使用Visual Studio 2012 Ultimate和Oracle Developer Tools for Visual Studio 11.2.0.3.20
  • Performing queries using LINQ to Entity 使用LINQ to Entity执行查询

So here's my problem: I have some entities that I've created with Oracle Developer Tools for Visual Studio (11.2.0.3.20). 所以这就是我的问题:我使用Oracle Developer Tools for Visual Studio(11.2.0.3.20)创建了一些实体。 Some of the entities return results fairly quickly. 一些实体很快就会返回结果。 However, with others that are querying against a view/table that contains more than 20 million records, it is consistently taking 10 minutes to return results (I've verified this time via unit tests) for this simple query: 但是,对于查询包含超过2000万条记录的视图/表的其他人,对于这个简单的查询,一直需要10分钟才能返回结果 (我已通过单元测试验证了这一次):

var member = (from m in context.Members
              where m.MemberID.Equals(memberId, StringComparison.OrdinalIgnoreCase)
              select m).FirstOrDefault();

I used to be using Devart dotConnect for Oracle which worked really well...but my company isn't renewing their license for this product and have told me to use the new Oracle Developer Tools for Visual Studio to accomplish things. 我曾经使用Devart dotConnect for Oracle ,它工作得很好......但是我的公司没有更新这个产品的许可证,并告诉我使用新的Oracle Developer Tools for Visual Studio来完成任务。

As a work around, I've made a direct connection to the database using OracleCommand provided by ODP.NET (Oracle.DataAccess.dll) and I get results back in less than a second. 作为一种解决方法,我使用ODP.NET(Oracle.DataAccess.dll)提供的OracleCommand直接连接到数据库,我在不到一秒的时间内得到了结果。 Same with doing other queries directly against the database using a management client. 与使用管理客户端直接对数据库执行其他查询相同。

My best guess as to why this is happening would be that perhaps Entity is loading the entire database into memory and then running my queries on it...which would be horrible, but I really don't believe that is what is happening. 关于为什么会发生这种情况我最好的猜测是,实体可能正在将整个数据库加载到内存中,然后在其上运行我的查询...这将是可怕的,但我真的不相信这是正在发生的事情。

Can someone please explain why this is happening and how I can fix it using Entity so that I don't have to manually rewrite all of my DB queries? 有人可以解释为什么会发生这种情况以及我如何使用Entity修复它以便我不必手动重写所有数据库查询?


UPDATE: 更新:
So I found the reason that my queries were taking 10 minutes to complete. 所以我找到了我的查询需要10分钟才能完成的原因。 I (with my very little experience with databases) had put this in my EDMX file: 我(我对数据库的经验很少)把它放在我的EDMX文件中:

...
<EntityContainer Name="MyStoreContainer">
  <EntitySet Name="MY_TABLE" EntityType="MyDB.Store.MY_TABLE" store:Type="Views" store:Schema="MYUSERNAME" store:Name="MY_TABLE">
    <DefiningQuery>
      SELECT
      "MY_TABLE"."COL1" AS "COL1",
      "MY_TABLE"."COL2" AS "COL2",
      "MY_TABLE"."COL3" AS "COL3",
      "MY_TABLE"."COL4" AS "COL4",
      "MY_TABLE"."COL5" AS "COL5",
      "MY_TABLE"."COL6" AS "COL6",
      "MY_TABLE"."MEMBERSHIP_ID" AS "MEMBERSHIP_ID",
      "MEMBERS"."EXTRA_INFO1" AS "EXTRA_INFO1",
      "MEMBERS"."EXTRA_INFO2" AS "EXTRA_INFO2"
      FROM "MYUSERNAME"."MY_TABLE" "MY_TABLE"
      LEFT JOIN "MYUSERNAME"."MEMBERS" ON "MY_TABLE"."MEMBERSHIP_ID" = "MEMBERS"."MEMBER_ID"
    </DefiningQuery>
  </EntitySet>
...

Turns out that the LEFT JOIN takes about 10 minutes when directly querying with a management client as well. 事实证明,直接查询管理客户端时, LEFT JOIN大约需要10分钟。 So I took the LEFT JOIN out...and now I see an increase in speed. 所以我把LEFT JOIN拿出来......现在我看到了速度的提高。 Here's the catch, this EntitySet was NOT the EntitySet that I was querying against when I was getting really slow responses. 这是捕获,这个EntitySet不是我在查询时反应非常慢的EntitySet。 I still get a response about 4-5 times faster if I manually write the code with OracleCommand . 如果我用OracleCommand手动编写代码,我仍会得到大约4-5倍的响应。
Can anyone explain why Entity is slowing things down so much and when I am not even accessing this left join query? 任何人都可以解释为什么实体正在减慢这么多,当我甚至没有访问这个左连接查询?

Wrap your input parameter with EntityFunctions.AsNonUnicode(memberId) . 使用EntityFunctions.AsNonUnicode(memberId)包装输入参数。

var member = (from m in context.Members
          where m.MemberID.Equals(EntityFunctions.AsNonUnicode(memberId), StringComparison.OrdinalIgnoreCase)
          select m).FirstOrDefault();

See https://community.oracle.com/message/10725648 请参阅https://community.oracle.com/message/10725648

An other solution is to update your oracle provider! 另一个解决方案是更新您的oracle提供程序! Odac 12c fix this problem : https://community.oracle.com/message/11065799#11065799 Odac 12c解决了这个问题: https ://community.oracle.com/message/11065799#11065799

It will prevent you from changing all your query with EntityFunctions.AsNonUnicode() 它将阻止您使用EntityFunctions.AsNonUnicode()更改所有查询

We had a similar performance issue. 我们遇到了类似的性能问题。 Thanks @CameronP for the suggestion to use the EntityFunctions.AsNonUnicode, which fixed the performance issue. 感谢@CameronP建议使用EntityFunctions.AsNonUnicode,它修复了性能问题。 Our project uses EF6 with Oracle 12.1* Managed Data Access. 我们的项目使用EF6和Oracle 12.1 *托管数据访问。 Instead of making the change to every EF query parameter, we used the TypeName attribute on the Entity Model and it worked ! 我们在实体模型上使用了TypeName属性而不是对每个EF查询参数进行更改,而且它有效!

Public Class Table1
    <Column("COLUMN_1", TypeName:="VARCHAR2")>
    Public Property Column1 As String
End Class 

Another trick is to disable Lazy Loading. 另一个技巧是禁用延迟加载。

If you can disable, do it. 如果你可以禁用,那就去做吧。

Example when you can't disable Lazy Loading: 无法禁用延迟加载时的示例:

When you have a table called Customers. 当你有一个名为Customers的表。 Then, when you call something like this: 然后,当你打这样的话:

var obj = myCustomerList.FirstOrDefault().ORDERS.ToList()

If you have code that access childrens, you can't disable the Lazy Loading 如果您有访问子级的代码,则无法禁用延迟加载

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM