【问题标题】:Executing Oracle Explain Plan in C#在 C# 中执行 Oracle 解释计划
【发布时间】:2017-03-11 00:19:27
【问题描述】:

通常,对 sql 语句执行“解释计划”会导致记录插入到 plan_table 中。当通过 TOAD 执行时,这对我来说很好。我的要求是通过我的 c# 应用程序(Oracle.DataAccess.Client lib)执行此操作。不幸的是,在 TOAD 上工作的同一语句在 C# 中执行时不会导致将任何记录插入 plan_table。

奇怪的是,尽管没有记录插入到表中,但我确定在 C# 中执行时会消耗 plan_id 序列。我可以通过在 TOAD 中执行新的解释计划来确认这一点,并注意到 plan_id 序列已根据我通过 C# 进行的尝试次数跳过。 Notice how it went from 44 to 50.

我需要特别解释计划的原因是我想在执行之前获取给定查询中涉及的表和列的列表。我考虑过语法解析,但考虑到 plan_table 记录包含我想要的数据,感觉就像是在重新发明轮子。

出于所有意图和目的,同一用户登录 TOAD 和 C#,因此我不怀疑权限有限。我尝试了有无承诺。我还尝试将解释计划放在存储过程中,并在 C# 中调用它,结果相同。 (在 TOAD 上按预期工作,但在 C# 上没有插入记录)。为了让它在存储过程中工作,我必须让它立即执行。

myoracon.Open();
OracleCommand myoracom = myoracon.CreateCommand();
myoracom = new OracleCommand("explain plan set statement_id = 'xd' for select * from employee", myoracon);
OracleTransaction trx;
trx = myoracom.Connection.BeginTransaction();
myoracom.Transaction = trx;
myoracom.ExecuteNonQuery();
trx.Commit();
myoracon.Close();

所以,在这一切之后,我的问题如下:为什么 C# 中的解释计划不会导致将记录插入到 plan_table 中,我该怎么做才能让它工作?

提前致谢!

【问题讨论】:

    标签: c# oracle stored-procedures oracle11g


    【解决方案1】:

    解释计划写在具体的表PLAN_TABLE中。您需要选择它以查看确切的计划。检查Using EXPLAIN PLAN

    EXPLAIN PLAN FOR
    SELECT last_name FROM employees;
    

    这将计划解释到 PLAN_TABLE 表中。然后您可以选择 来自 PLAN_TABLE 的执行计划。如果您没有,这很有用 PLAN_TABLE 中的任何其他计划,或者如果您只想查看最后一个 声明。

    在您的情况下,您将使用您设置的特定 ID 来选择它。

    所以你需要另一个到 db 的连接:

    using(OracleConnection conn = new OracleConnection(oradb))
    {
        conn.Open();
        OracleCommand cmd= conn.CreateCommand();
        cmd.Connection = conn;
    
        cmd.CommandText = @"Select * FROM Plan_Table Where ID=@ID";
        cmd.Parameters.AddWithValue("@ID", idWhichYouSpecify);
    
        DataTable tbl = new DataTable();
    
        using(OracleDataAdapter da = new OracleDataAdapter(cmd))
        {
            da.Fill(tbl);
        }
    }
    

    【讨论】:

    • 感谢您的回复。我没有提到这仍然是一个概念证明,我只是想检查解释计划是否会成功执行。目前,我正在通过 TOAD 手动查找 plan_table 以检查在 C# 中执行时解释计划是否按预期工作。
    • @Mr.Wright 你也可以像我写的那样从 C# 中的 plan_table 加载信息。
    【解决方案2】:

    您是否控制了表格:TOAD_PLAN_TABLE 您在 C#

    上运行脚本的用户

    如果它不存在,则在您的 c# 用户下手动创建它:

    CREATE TABLE **your_user**.TOAD_PLAN_TABLE
    (
      STATEMENT_ID       VARCHAR2(30 BYTE),
      PLAN_ID            NUMBER,
      TIMESTAMP          DATE,
      REMARKS            VARCHAR2(4000 BYTE),
      OPERATION          VARCHAR2(30 BYTE),
      OPTIONS            VARCHAR2(255 BYTE),
      OBJECT_NODE        VARCHAR2(128 BYTE),
      OBJECT_OWNER       VARCHAR2(30 BYTE),
      OBJECT_NAME        VARCHAR2(30 BYTE),
      OBJECT_ALIAS       VARCHAR2(65 BYTE),
      OBJECT_INSTANCE    INTEGER,
      OBJECT_TYPE        VARCHAR2(30 BYTE),
      OPTIMIZER          VARCHAR2(255 BYTE),
      SEARCH_COLUMNS     NUMBER,
      ID                 INTEGER,
      PARENT_ID          INTEGER,
      DEPTH              INTEGER,
      POSITION           INTEGER,
      COST               INTEGER,
      CARDINALITY        INTEGER,
      BYTES              INTEGER,
      OTHER_TAG          VARCHAR2(255 BYTE),
      PARTITION_START    VARCHAR2(255 BYTE),
      PARTITION_STOP     VARCHAR2(255 BYTE),
      PARTITION_ID       INTEGER,
      OTHER              LONG,
      DISTRIBUTION       VARCHAR2(30 BYTE),
      CPU_COST           INTEGER,
      IO_COST            INTEGER,
      TEMP_SPACE         INTEGER,
      ACCESS_PREDICATES  VARCHAR2(4000 BYTE),
      FILTER_PREDICATES  VARCHAR2(4000 BYTE),
      PROJECTION         VARCHAR2(4000 BYTE),
      TIME               INTEGER,
      QBLOCK_NAME        VARCHAR2(30 BYTE),
      OTHER_XML          CLOB
    )
    

    【讨论】:

    • 哇,非常感谢。我不敢相信它是那么简单!我将您上面的创建脚本与我的环境 plan_table 的实际描述进行了比较。 OTHER_XML 列的位置不同(非常小的细节),但我只是测试了它并且它有效。我想问题是需要在我的模式中定义 PLAN_TABLE 。再次感谢! :D
    猜你喜欢
    • 2020-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-09
    • 2012-11-12
    • 2012-12-16
    • 2012-05-21
    • 1970-01-01
    相关资源
    最近更新 更多