希望有人可以对我目前使用Oracle数据库的问题有所了解 - 我确信这很简单!!
我已经设法在一个示例中重新创建了这个,所以这里是数据库结构:
CREATE TABLE MyTable(
ixMyTable NUMBER,
clobData CLOB
)
/
CREATE OR REPLACE PACKAGE PKGTEST
AS
PROCEDURE DoSomething(
cur_OUT OUT SYS_REFCURSOR
);
END PKGTEST;
/
CREATE OR REPLACE PACKAGE BODY PKGTEST
AS
PROCEDURE DoSomething(
cur_OUT OUT SYS_REFCURSOR
)
AS
BEGIN
OPEN cur_OUT FOR
SELECT ixMyTable, clobData
FROM MyTable;
END;
END PKGTEST;
/
GRANT EXECUTE ON PKGTEST TO TEST_ROLE
/
BEGIN
FOR i IN 1 .. 7000 LOOP
insert into mytable values (i, TO_CLOB('123456'));
END LOOP;
END;
/
额外信息:
架构所有者是TEST_SCHEMA
用户是CARL
CARL具有TEST_ROLE角色
鉴于上面的数据库设置,我有一个C#测试应用程序,它使用标准的System.Data.OracleClient.OracleCommand等来执行PKGTEST.DoSomething并将结果抛出到数据网格(DevExpress)。
非常确定网格在这里是不相关的,因为我们使用开源OTL(不幸的是我的部门)通过c ++遇到了同样的问题。
好的,问题....
从开始到网格填充的时间是~35-40s,哎哟。
但是,如果我执行以下操作:
GRANT SELECT ON MyTable TO TEST_ROLE
/
然后再次执行查询,需要5-6秒。
在我看来,这与特权等有关,但我不太确定为什么它仍然可以双向工作?
如果我将程序更改为
,只需将其他内容扔进底池SELECT ixMyTable, TO_CLOB(TO_NCLOB(clobData))
FROM MyTable;
然后时间是〜5-6s,有或没有额外的SELECT权限。
非常感谢任何指针或直接解决方案!
编辑:
操作系统是Vista x86 Business
Oracle Server是10.2.0.1
Oracle客户端是10.2.0.3
编辑:
正如所建议的那样,我尝试从MS OracleClient更改为ODP.NET,这确实可以根据需要加快速度。
不幸的是,受影响的C#应用程序只是一个内部应用程序,用于查看表/运行SPROCS等。
我们的主要交付成果是使用OTL(http://otl.sourceforge.net/otl3_intro.htm)进行数据库访问的C ++应用程序。这不是真正可以在这个时候改变的东西,所以我真的想了解差异的原因,而不必在willy-nilly周围抛出无偿的GRANT SELECT。
如果没有SELECT权限导致完全失败,那么我可能会接受这一点,但是缺少SELECT似乎会导致访问CLOB数据的路径变慢。
我已经标记了3个答案 - 感谢那些 - 但我确实有理由这样做,所以我会为此添加一笔赏金。
P.S。我们真的很想在OCCI开始时使用OCCI,但是由于Oracle始终支持IDE的一个版本,因此我们无法在Visual Studio 2008中很好地使用它。
答案 0 :(得分:6)
您是否确定每次都从磁盘读取blob,而不是从磁盘缓存中读取第二个及以下内容?
我已经在性能测试中看到了这个问题,特别是在Oracle上,第一次测试运行非常糟糕。然后,有一个小的(并且看似微不足道的变化),性能突然显着提高。但实际上发生的事情是,您查询的数据已加载到缓存中,并且可以以10倍或20倍的速率访问(内存与磁盘)。
执行此测试的正确方法是在查询运行之间退回数据库。如果DBA不允许您为此测试退回测试生产服务器,请在您的计算机上加载Oracle XE的副本。
编辑:或者更好:每次都删除并重新创建表格。你可能会这样做,但没有提到它。
答案 1 :(得分:1)
我会尝试使用odp.net http://www.oracle.com/technology/tech/windows/odpnet/index.html而不是System.Data.OracleClient。
答案 2 :(得分:1)
根据上面的建议,您可以尝试不同的ODBC驱动程序或客户端软件。 TO_CLOB(TO_NCLOB())
工作得如此之快的事实,直的似乎并不表明问题存在的地方。
首先,我将采用两个查询并通过SQLDeveloper运行它们并获得解释计划。这应该为您提供在Oracle端执行的基准。添加转换应该对执行路径没有影响。交替运行查询并计算时间以查看它们的速度。如果没有区别,我建议客户端软件是你的问题。
如果我的假设是正确的,这也可以解释GRANT SELECT
的变化。客户端软件正在对CLOB进行某种昂贵的转换。授权和/或显式转换允许客户端避免这种情况。我不知道为什么。
答案 3 :(得分:1)
我知道这是一个非常古老的问题
我是根据我使用 Oracle OCCI 库的经验发言的,但我相信这适用于任何 Oracle 客户端。 blob/clob 读操作慢的原因如下
set arraysize 1
& set arraysize 5000
来处理带有 & 不带 blob/clob 列的表。对于具有大量记录且没有 blob/clob 列的表,arraysize
会产生很大的不同。对于带有 blob/clob 列的表,它不会有太大区别。因此读取每条记录将往返于服务器。在较慢的网络(例如 WAN)上,这会产生很大影响请看这里。 https://docs.oracle.com/cd/E18283_01/appdev.112/e10646/oci07lob.htm#CHDDHFAB
您可以通过为 LOB 启用行预取来缓解这种情况。 https://docs.oracle.com/en/database/oracle/oracle-database/12.2/jajdb/index.html?oracle/jdbc/OracleStatement.html
我从来没有让这个为 OCCI 工作,但实现了这里提到的解决方法 (Is there a way to prefetch LOBs data in occi?)
答案 4 :(得分:0)
老实说,我认为问题在于OTL驱动程序和OracleClient在处理来自SYS_REFCURSOR的CLOB时遇到问题。 SYS_REFCURSOR很弱,这意味着游标本身可以返回任何类型的数据,这意味着驱动程序需要不断返回数据库并查询游标的元数据(即获取游标中的数据类型),然后加载CLOB流,然后加载数据。显然,如果执行查询的用户可以访问正在查询的表,则驱动程序可以更好地检索元数据并返回正确的数据。
更改存储过程以返回强大的ref_cursor工作吗?
CREATE OR REPLACE PACKAGE PKGTEST
AS
TYPE C_DoSomething IS REF CURSOR RETURN MyTable%ROWTYPE;
PROCEDURE DoSomething(
cur_OUT OUT c_DoSomething
);
END PKGTEST;
您是否可以更改存储过程以执行TO_CLOB()
,因为这似乎也有效?
答案 5 :(得分:0)
您的数据库的NLS_CHARACTERSET和NLS_NCHAR_CHARACTERSET是什么。运行
select * from nls_database_parameters;
获得结果。您的客户端软件的NLS_LANG设置是什么?
这可以更深入地了解问题,并有助于回答TO_CLOB(TO_NCLOB())调用的成本。
答案 6 :(得分:0)
这些并非都必然是直接相关的,但你可能应该检查每一个是否相关。我怀疑这是缓存相关的:一旦你完成了第一个查询,你就应用select然后它会很快。在中间你必须反弹服务器,以摆脱缓存,如果你想要正确地进行性能测试。如果您执行此测试并且突然执行得更好,请尝试将表固定到缓存中。请参阅下面围绕clob存储内联,因为这可能是相关的。
我在Oracle 10g中一年左右就出现了clob性能方面的问题。一旦我们获得了令人敬畏的dba帮助,我们就能解决大部分问题。花了大约2个月才使表演达到足够的速度。
您使用的是哪个版本的Oracle? 在Oracle 10g(早期版本)中,clob性能存在大量问题。实际上,在某些情况下,实际上只使用两个表和一个varchar列(将varchars连接在一起,然后使用clob)实际上更快。我们升级到更高版本,它更好
您的数据存储在哪里? 还有一个选项可以将clob存储在表中。根据您的数据大小,您可能会发现这有助于提高性能。 如果您已将数据存储在SAN上,那么还应该查看SAN上的缓存大小以及块大小。当缓存大小不正确时,Oracle + SAN可能会有点滑稽。
另一种解决方法: 如果您发现持久性很慢或甚至访问速度很慢且您没有CPU限制,请压缩数据并将其存储在blob中。我们在这里也看到了很大的性能优势。
如果你在处理clobs的任何事情上看到性能问题(内存相关?),我们发现我们会将对象重新创建为新字符串。即使数据较小,驱动程序也预先创建了32K大小的字符串。
我确实想知道系统表是否可能碎片化了?有很多表/模式吗?同义词怎么样?
此外,当您存储clobs时,它们是否存储在Oracle中的一个大型文件中?如果我没记错的话你必须小心分裂;存储不会被释放以供重用。
也许您可以将.NET Web服务放在数据库前面?如果您无法解决性能问题,那么这可能是一种选择。