【问题标题】:Prepared statement vs. Stored Procedure with RefCursor准备好的语句与带有 RefCursor 的存储过程
【发布时间】:2011-09-09 19:26:00
【问题描述】:

我一直在调用在我的 C# 应用程序中返回 RefCursors 的 Oracle 存储过程。下面给出了一个示例存储过程。

CREATE OR REPLACE
PROCEDURE "DOSOMETHING"(
    P_RECORDS OUT SYS_REFCURSOR)
AS
BEGIN
    OPEN P_RECORDS FOR
    SELECT SOMETHING FROM SOMETABLE;
END;

当使用OracleDataReader 读取结果时,每次调用该过程时,数据库都会解析该过程。经过大量搜索后,我发现使用RefCursor 时,.NET 无法消除此解析调用。

但是,如果我只使用如下准备好的语句调用该过程,则可以避免此解析调用。

public void DoSomething()
{
    var command = ServerDataConnection.CreateCommand();
    command.CommandType = CommandType.Text;
    command.CommandText = "SELECT SOMETHING FROM SOMETABLE";
    command.Prepare();

    using (var reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            DoSomethingToResult();
        }
    }
}

我的问题是,这些方法中的哪一种对性能的影响最小?将过程更改为准备好的语句以避免解析调用会对应用程序性能产生更大的负面影响吗?

请注意,这些选择语句可能会返回大量结果。可能有数千行。

【问题讨论】:

    标签: c# .net performance oracle oracle11g


    【解决方案1】:

    在 PL/SQL 中使用引用游标将在每次打开游标时引发解析调用。每次调用command.Prepare() 时都会发出相同的解析调用。就像现在一样,您的 .NET 代码将解析查询,就像解析 PL/SQL 代码一样。

    如果您需要发出完全相同的查询(只需更改参数),您可以重用您的命令对象而无需额外的解析调用。但是,这些解析将是软解析,因此性能可能不明显(大部分工作是在硬解析中完成的,即数据库第一次遇到查询时)。由于您的查询返回大量行,因此与实际获取这些行的工作量相比,软解析所涉及的工作量肯定可以忽略不计。

    【讨论】:

    • 是的,我做了这个改变,现在我的语句没有解析那么多。是的,在实际代码中,我正在重用我的命令对象。感谢您的回复。
    猜你喜欢
    • 1970-01-01
    • 2010-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多