代码之家  ›  专栏  ›  技术社区  ›  Greg Smalter

来自.NET应用程序的Oracle查询速度慢(或失败),但来自SQL开发人员的查询速度快

  •  10
  • Greg Smalter  · 技术社区  · 15 年前

    我们使用odp.net在Oracle数据库上执行查询,通常它可以正常工作。但是,有一个特定的数据库和该数据库中的一个特定视图,我们无法从.NET完成查询。例如:

    SELECT some_varchar_field FROM the_view WHERE ROWNUM < 5;
    

    如果我在OracleSQLDeveloper中执行这个查询,它将在不到一秒钟的时间内完成。如果我使用odp.net从我们的.NET应用程序执行相同的查询,它将挂起并最终产生“ora-03135:connection lost contact”错误。我认为把它限制在几行就消除了它被当作束缚问题的可能性。

    我还可以成功地执行其他查询,但它们在我们的程序中比在SQL开发人员中慢。同样,我认识到SQL开发人员最初只获取前50行的数据,但我认为rownum条件将其从等式中去掉。

    Oracle SQL开发人员正在使用的连接或命令与我们的应用程序正在使用的连接或命令之间可能有什么不同,这会导致速度差异?

    不幸的是,我没有访问服务器的权限(除了针对它运行Oracle查询)。

    谢谢您。

    更新:我用微软的甲骨文供应商尝试过同样的查询,它执行得非常快。不幸的是,该提供程序已被弃用,因此这不是一个长期的解决方案。

    4 回复  |  直到 15 年前
        1
  •  12
  •   Greg Smalter    15 年前

    它与odp.net提供程序无关。问题是,我们用来为我们创建连接的库(当然,Oracle SQL开发人员没有使用它,而且我在尝试Microsoft提供程序时没有使用它)总是在执行任何操作之前执行以下语句:

    ALTER SESSION SET NLS_COMP = LINGUISTIC
    ALTER SESSION SET NLS_SORT = BINARY_CI
    

    这使得Oracle不区分大小写。但是,它们也使得所有常规索引都变得无用。因为我们是从视图中查询的,所以它内置了排序功能。因为我们没有数据库,所以我们不能用语言化的索引来解决性能问题。

    提供一种不在这个(很少)场景中执行这些语句的方法解决了这个问题。

        2
  •  4
  •   Gary Myers    15 年前

    直接的想法是

    1. CLOB、BLOB或长/长原始数据,仅几行就需要大量带宽。
    2. 无效数据(例如,有方法将无效日期输入日期字段,这可能会混淆某些客户机)
    3. “表”实际上不是一个表,而是一个视图或具有复杂派生的东西,或者在它上面有一个vpd/rls/fgac安全策略。
    4. 异域数据类型(空间或用户定义)。

    建议

    1. 显式列出列(例如,从rownum<5所在的_表中选择a、b、c)。逐个添加列,直到停止工作。假设表中至少有一个“简单”列。
    2. 检查v$session中的会话,查看wait事件是什么。DB服务器正在为此SQL燃烧CPU,或者它正在等待某个东西(可能是客户机)。
    3. 检查v$sql中的sql。是否有一个或多个子光标。是否有一个或多个计划哈希值?不同的子光标可以使用不同的计划。如果没有除rownum之外的where子句,这是不太可能的。
        3
  •  2
  •   Gary Myers    15 年前

    视图增加了不同程度的复杂性。 “从表中选择列,其中rownum<5”可能只有一个解释计划,从单个本地对象中选择数据。

    对于视图,应该从获取视图文本开始 SELECT TEXT FROM ALL_VIEWS WHERE VIEW_NAME = ...

    odp.net和SQL开发人员会话之间有很多不同之处。我会考虑NLS参数(如日期格式)和字符集设置。

    如果你能在v$sql中找到SQL,你可以做一个dbms-xplan.display-cursor(sql-id)来查看不同的计划,看看你是否能找出问题所在。

        4
  •  0
  •   Paul Farry    15 年前

    在我前雇主的一个项目中,我们使用odp.net与一个大型零售系统数据库交谈,我们会发现连接丢失错误。

    这需要花费大量的努力来证明,但最终它成为了Oracle数据库中的一个损坏索引,而这个索引只受到我们查询的影响。DBA最终将其跟踪到执行查询时在Sun Box上运行的进程的核心转储。我们没有使用任何类型的查询提示等,但是当我们在toad中运行相同的查询时,它没有命中这个特定的索引。奇怪?& & lt;

    推荐文章