从 ODBC 读取器读取 Oracle CLOB 数据非常慢
Reading Oracle CLOB data from ODBC reader is super slow
我们正在使用 C# 和 .Net 4.5 从 Oracle 数据库下载数据。
values[]
是对象数组;
reader 是 ODBC 读取器,它与 Oracle 数据库 table 和 CLOB 数据建立了开放连接。
相关代码如下:
if (reader.Read())
{ //Download and save the values
for (int x = 0; x < reader.FieldCount; x++)
{ //Populate all the values
values[x] = reader[x]; //this line seems to cause execution to hang
}
//
//blah blah blah
//
}
C#代码好像挂在了values[x] = reader[x];
.
线上
我们将读取的行中的每一列分配给一个特殊的对象数组,因为我们需要稍后对该数据执行单独的操作,而现在不必担心数据类型。
问题在于,当 table 遇到一个很大 (> 28,000) 的 Oracle CLOB 数据列时,该行似乎永远不会完成。
如果我们从 odbc 读取器读取的内容中删除 CLOB 列,一切都会完美无缺。
问题:
- 为什么会这样?数组赋值不是应该比较快吗?
- 有哪些可能的变通方法可以让我们在下载的数据中保留 CLOB 列?我们
需要将 ODBC 阅读器保持为通用 ODBC 阅读器(而不是特定于 Oracle)。
应用程序已编译,必须保持 32 位。
谢谢!
除非有真正令人信服的理由使用 ODBC,否则最好使用 ODP.net 或托管 ODP.net。虽然我不能 100% 肯定地说 ODBC 是您的问题,但我可以告诉您我已经多次将 .NET 与 LOB 一起使用,没有问题,使用 ODP.net。我还可以告诉你,Microsoft 的 Oracle 驱动程序(已删除)引起了无数神秘问题,其中大部分与性能有关。例如,查询 1 工作正常,但用绑定变量替换文字会导致执行延迟 15 秒。使用 ODP.net,延迟消失。我的猜测是ODBC可能有类似的神秘问题。
ODP.net(或 DevArt dotConnect)是我所知道的仅有的两个使 .NET 能够利用 OCI 的工具,OCI 具有批量插入和更新等强大功能。 OCI 可能有更好的方法来处理大型 LOB。您是否有必须使用 ODBC 的令人信服的理由?
问题出在 CLOB 类型上!
将其转换为 varchar
并且性能还可以:
改变
select clob from table
至 2 次选择
select DBMS_LOB.SUBSTR(clob,4000,1) from table where length(clob)<= 4000;
select clob from table where length(clob)> 4000;
很容易验证 - 小的 clob 列的性能很慢,但转换为 varchar 可以解决问题![=13=]
问题是每个 CLOB 列提取都会发出 2 次从客户端到服务器的额外网络往返!
通常情况下,多行需要一次净往返
添加LONGDATACOMPAT=1;在您的字符串连接上:
string conn = @"DSN=database;UID=user;PWD=password;LONGDATACOMPAT=1;";
我们正在使用 C# 和 .Net 4.5 从 Oracle 数据库下载数据。
values[]
是对象数组;
reader 是 ODBC 读取器,它与 Oracle 数据库 table 和 CLOB 数据建立了开放连接。
相关代码如下:
if (reader.Read())
{ //Download and save the values
for (int x = 0; x < reader.FieldCount; x++)
{ //Populate all the values
values[x] = reader[x]; //this line seems to cause execution to hang
}
//
//blah blah blah
//
}
C#代码好像挂在了values[x] = reader[x];
.
我们将读取的行中的每一列分配给一个特殊的对象数组,因为我们需要稍后对该数据执行单独的操作,而现在不必担心数据类型。
问题在于,当 table 遇到一个很大 (> 28,000) 的 Oracle CLOB 数据列时,该行似乎永远不会完成。
如果我们从 odbc 读取器读取的内容中删除 CLOB 列,一切都会完美无缺。
问题:
- 为什么会这样?数组赋值不是应该比较快吗?
- 有哪些可能的变通方法可以让我们在下载的数据中保留 CLOB 列?我们 需要将 ODBC 阅读器保持为通用 ODBC 阅读器(而不是特定于 Oracle)。
应用程序已编译,必须保持 32 位。
谢谢!
除非有真正令人信服的理由使用 ODBC,否则最好使用 ODP.net 或托管 ODP.net。虽然我不能 100% 肯定地说 ODBC 是您的问题,但我可以告诉您我已经多次将 .NET 与 LOB 一起使用,没有问题,使用 ODP.net。我还可以告诉你,Microsoft 的 Oracle 驱动程序(已删除)引起了无数神秘问题,其中大部分与性能有关。例如,查询 1 工作正常,但用绑定变量替换文字会导致执行延迟 15 秒。使用 ODP.net,延迟消失。我的猜测是ODBC可能有类似的神秘问题。
ODP.net(或 DevArt dotConnect)是我所知道的仅有的两个使 .NET 能够利用 OCI 的工具,OCI 具有批量插入和更新等强大功能。 OCI 可能有更好的方法来处理大型 LOB。您是否有必须使用 ODBC 的令人信服的理由?
问题出在 CLOB 类型上!
将其转换为 varchar
并且性能还可以:
改变
select clob from table
至 2 次选择
select DBMS_LOB.SUBSTR(clob,4000,1) from table where length(clob)<= 4000;
select clob from table where length(clob)> 4000;
很容易验证 - 小的 clob 列的性能很慢,但转换为 varchar 可以解决问题![=13=]
问题是每个 CLOB 列提取都会发出 2 次从客户端到服务器的额外网络往返!
通常情况下,多行需要一次净往返
添加LONGDATACOMPAT=1;在您的字符串连接上:
string conn = @"DSN=database;UID=user;PWD=password;LONGDATACOMPAT=1;";