【问题标题】:Why given query hangs or slow down?为什么给定的查询挂起或变慢?
【发布时间】:2019-10-31 01:00:55
【问题描述】:

通常,它执行正常,但有时一周一两次,它在 Oracle 中被挂起或减速。

有没有更好的优化方法?

FOR i IN ( SELECT * FROM process_data) LOOP
    BEGIN
        SELECT employee_plan_id
          INTO lc_emp_plan_id
          FROM employee
         WHERE employeeid = i.emp_id
           AND join_year = (
            SELECT join_year
              FROM employeedata
             WHERE employeeid = i.emp_id
               AND i.joining_date BETWEEN join_date AND termination_date
        );
    END;
    SELECT employee_plan_type
      INTO lc_emp_type
      FROM employee_plans
     WHERE employee_plan_id = lc_emp_plan_id;

    -- Mark failed record if emp_lastname is null
    UPDATE process_data
       SET
        is_failure = 1
     WHERE emp_lastname IS NULL
       AND emp_plan_type = lc_emp_type;
END LOOP;

记住

SELECT join_year
  FROM employeedata
 WHERE employeeid = i.emp_id
   AND i.joining_date BETWEEN joining_date AND termination_date;

它总是会返回 1 条记录,这是被证明的。

这里lc_emp_plan_id是一个变量,这个for循环在过程中执行?

【问题讨论】:

  • 我看到两种可能性:要么你的数据包含一些奇怪的东西,例如您的子查询返回一万亿行(您说这被证明是错误的),或者服务器上存在其他一些资源争用(例如锁定)。你查看过服务器的内存、CPU 和磁盘使用情况吗?
  • 谓词中的joining_datetermination_date 是什么?它们是参数还是只是列名?
  • 你为什么要循环播放?在您的真实代码中,循环中正在做什么?您是否在更新、插入等内容?
  • 请更新您的问题以包含更新声明。您很可能在这里不必要地循环播放,但没有更多信息,很难说。
  • 您的更新语句是否应该以某种方式链接回外部光标?

标签: sql oracle oracle11g query-optimization


【解决方案1】:

对观察到的行为最自然的解释是,要处理的行数 (process_data) 会有所不同。 总运行时间与处理的行数成线性比例,因此在有很多行的日子里,循环“挂起”。

加速 a 的最佳方法是不要在 PL/SQL 中使用 FOR LOOP

在 SQL 语句中简单地重新构造它(这并不总是可能的,有时会导致复杂的 SQL,但可能会产生显着的加速。

在你的情况下,这应该是一个相当简单的练习:

此查询返回与您的第一个循环相同的结果。

SELECT e.employee_plan_id
  FROM process_data p
  JOIN employee e ON p.emp_id = e.employeeid
  JOIN employeedata ed ON p.emp_id = ed.employeeid
   AND p.joining_date BETWEEN ed.join_date AND ed.termination_date;

因此,您可以使用一条 UPDATE 语句重写整个过程。

UPDATE process_data
   SET is_failure = 1
 WHERE emp_lastname IS NULL
   AND emp_plan_type IN (
    SELECT employee_plan_type
      FROM employee_plans
     WHERE employee_plan_id IN (
        /* copy the query above here */
    )
);

【讨论】:

  • 这很有用,但是在所有地方(甚至复杂的地方)都删除它很烦人......但是我发现表employeedata有时会在进行简单选择时产生问题......任何其他解决方案将不胜感激.
  • 如果您对特定查询有疑问,请打开一个新问题并只关注它。您需要为查询提供更多详细信息,至少是执行计划。请检查例如here你应该提供什么信息
猜你喜欢
  • 2012-08-20
  • 1970-01-01
  • 2021-10-12
  • 1970-01-01
  • 2022-01-08
  • 2017-01-21
  • 2022-12-13
  • 1970-01-01
  • 2017-10-12
相关资源
最近更新 更多