首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在.Net中有效地处理从Oracle读取CLOB慢的问题?

如何在.Net中有效地处理从Oracle读取CLOB慢的问题?
EN

Stack Overflow用户
提问于 2013-12-12 17:43:50
回答 1查看 6.2K关注 0票数 2

在我的公司,我们有一个WPF应用程序,它可以连接到不同的数据库( MySQL,MySQL,SQLite和Oracle)。我们有许多表(有时是200+,不要问为什么,它非常复杂),我们的数据访问层有几个接口和虚拟/覆盖方法来处理特定数据库中的数据读取。这一点很重要,因为正如大多数教程所示,我们并不是专门在一个表上工作,而是动态创建了我们需要运行的特定于数据库的命令。在MS SQL、MySQL和SQLite下,一切都运行得很好,但在Oracle CLOB中读取速度非常慢。读取2000行数据需要40-50秒。不幸的是,在大多数情况下,我们不能假设我们不需要CLOB类型,因为我们正在以xml格式存储财务数据,有时它会超过4000,8000,甚至10k+字符长大小。我正在使用ODP.Net解决方案读取数据,这就是我正在做的事情:

我们的环境: Oracle: 11.2.0.1.0 VS: 2010,从我的Oracle主安装: C:\Oracle\ODP.NET\bin\4\Oracle.DataAccess.dll引用了专业版Oracle.DataAccess.dll

我的测试代码(来自我们的解决方案):

属性:

private string ConnectionString
{
   get
   {
      return
         string.Format(
         "User Id={0}; Password={1}; POOLING=true;
         Data Source= (DESCRIPTION=(ADDRESS=
         (PROTOCOL=TCP)(HOST={2})(PORT={3})) (CONNECT_DATA=(SID={4})
         (SERVICE_NAME={5})));",
         "ourUser", "ourPassword", "ourHost", "ourPort", "ourSID",
         "ourDatabaseName");
        }
    }

要运行的命令:

string sql = "SELECT * FROM OurTable";
//This table contains at least one CLOB column

和我们的测试代码:

List<object[]> readerList = new List<object[]>();

using (Oracle.DataAccess.Client.OracleConnection oraConn = new
    Oracle.DataAccess.Client.OracleConnection(ConnectionString))
{
   oraConn.Open();
   Oracle.DataAccess.Client.OracleCommand oraComm = new
      Oracle.DataAccess.Client.OracleCommand(sql);
   oraComm.CommandType = CommandType.Text;
   oraComm.Connection = oraConn;
   Oracle.DataAccess.Client.OracleDataReader oraReader;
   oraReader = oraComm.ExecuteReader();
   oraComm.InitialLOBFetchSize = -1;

   while (oraReader.Read())
   {
      object[] readObjects = new object[oraReader.FieldCount];
      oraReader.GetValues(readObjects);
      readerList.Add(readObjects);
   }

  oraConn.Close();
}

while迭代运行非常慢,除非我们不需要读取CLOB,因为在这种情况下它会很快。不幸的是,我不能制定特定于表的解决方案,因为不是在所有情况下,我都知道我必须处理哪些表(有时会动态创建表)。

那么,问题是:有没有什么解决方案可以让它像从MS SQL中读取文本类型对象一样快?

EN

回答 1

Stack Overflow用户

发布于 2013-12-12 22:07:33

查看命令对象中的属性FetchSize,如下所示:Improve ODP.NET Performance

您可以像这样获得行的大小:

   Public Function GetRowSize(ByVal cmd As OracleCommand) As Integer
      Dim dr As OracleDataReader
         dr = cmd.ExecuteReader()
         Return CInt(dr.GetType.GetField("m_rowSize", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic).GetValue(dr))
   End Function

在C#中,它看起来像这样:

public int GetRowSize(OracleCommand cmd)
{
   OracleDataReader dr = cmd.ExecuteReader();
   return (int)( dr.GetType().GetField("m_rowSize", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(dr) );
}

当您的应用程序启动时,您可以为每个不同的查询执行一次此函数,然后您可以重用该值。

我记得前段时间我也遇到过类似的问题。我的解决方案是选择没有任何CLOB列的表。为了获得CLOB值,我只对单个CLOB列和单个记录运行了一个额外的SELECT (使用像您一样的OracelDataReader )。

我还找到了这个文档:Obtaining LOB Data

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20539886

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档