【问题标题】:ODP.Net Stored Procedure performance issues on large datasets大型数据集上的 ODP.Net 存储过程性能问题
【发布时间】:2010-12-24 14:26:31
【问题描述】:

在我们的一个数据库中进行 SELECT 查询时,我们遇到了一些主要的性能问题。请参阅下面的简单程序和相关代码。

在代码中,ExecuteReader() 方法在返回 30K 记录的查询上执行大约 10 秒。迭代 Reader 需要 2 分钟(即使我没有将数据泵入任何其他对象)。 30k 行数据集的 2 分钟对我们来说是不可接受的,因为我们期望数百万的数据集。

这里有什么让你们印象深刻的东西吗?希望您在 ODP.NET 和 PL/SQL 方面的经验可能会有所帮助。

    create or replace PROCEDURE              TRACKING_FETCH (
                p_tracking_id             IN NUMBER,
                p_parent_id               IN NUMBER,
                p_media_id                IN NUMBER,
                p_custodian_id            IN NUMBER,
                p_return_cursor           OUT SYS_REFCURSOR)
AS
BEGIN
     OPEN p_return_cursor FOR
            SELECT 
                  * 
            FROM
                  tracking
            WHERE
                  (tracking_id = p_tracking_id OR p_tracking_id = 0)
            AND   (parent_id = p_parent_id OR p_parent_id = 0) 
            AND   (media_id = p_media_id OR p_media_id = 0)
            AND  (custodian_id = p_custodian_id OR p_custodian_id = 0);
END TRACKING_FETCH;

--

using (DataFactory command 
       = new DataFactory(dbConnection, 
                         DatabaseType.Oracle, 
                         CommandType.StoredProcedure, 
                         "TRACKING_FETCH"))
{
       command.AddInParameter("p_tracking_id", DbType.Int32, trackingid);
       command.AddInParameter("p_parent_id", DbType.Int32, parentid);
       command.AddInParameter("p_media_id", DbType.Int32, mediaid);
       command.AddInParameter("p_custodian_id", DbType.Int32, custodianid);
       using (var dr = command.ExecuteReader())
       {
              while (dr.Read())
              {
                  //Do Things...
              }
       }
}

任何指导将不胜感激。

【问题讨论】:

    标签: oracle stored-procedures plsql odp.net


    【解决方案1】:

    这不是您的 odp.net 程序的问题。原因在于SELECT。如果表包含大量记录,则可能是优化器决定运行全表扫描,具体取决于您的参数。检查explain plan 语句的运行方式。如果您没有看到任何有用的信息。尝试trace 语句查看物理读取。

    【讨论】:

      【解决方案2】:

      值得研究一下 Oracle 等待接口。 我怀疑网络延迟正在杀死你。该过程正在返回一个指向结果集的指针。在您的循环中的某个时刻,我猜您正在获取行(即使它们被转储)。

      检查 v$sql 将告诉您正在执行多少次提取以及处理了多少行。一个一个除,你会看到每次提取有多少行。如果您正在执行 1 行/提取甚至 10-20 次,则需要数以千计的网络等待。如果您要拉回数百万条记录,则理想情况下每次提取需要数千行,尽管这可能会占用您的内存。

      根据您对数百万行的处理方式,可能值得重新考虑架构。例如,如果它们被转储到一个文件中,那么可能会在数据库服务器上生成该文件,压缩它,通过网络移动文件,然后解压缩它。

      【讨论】:

      • 是的,你说的延迟是对的,我没有意识到每次读取数据读取器都是一次往返。我们通过在 OracleDataReader 上设置“FetchSize”字段来解决这个问题,该字段告诉读者每次往返时要带回多少数据。感谢您的帮助。
      【解决方案3】:

      您是否尝试过在存储过程上运行EXPLAIN PLAN?我没有看到您的代码或存储过程有任何直接问题,但全表扫描会严重缩短查询的执行时间。解释计划会告诉您是否存在表扫描,然后您可以调整查询以加快速度。

      【讨论】:

        猜你喜欢
        • 2019-06-29
        • 2021-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多