复杂查询的MySQL存储过程需要5分钟

时间:2012-10-23 08:03:47

标签: mysql stored-procedures database-performance

此过程正常,但运行需要5分钟。有更快,更简单的方法吗?

我有一个包含检查列表的表。以后在同一张表中插入后续检查。后续检查具有相同的serial_number但具有不同的date_stamp。我需要找出哪些检查没有完成后续检查。

首先,我得到的是type_due = 3的所有serial_numbers,并且没有标记为inspection_completed。

然后,从这个serial_numbers列表中,我正在检查在以后的date_stamp中是否存在具有相同serial_number的检查,该date_stamp被标记为inspection_completed。

所以只有当其他东西存在时它才是选择;如果第二个查询中的结果具有相同的serial_number,更大的日期和一个非null的inspection_completed值,则在第一个查询中消除结果池。

每次运行此查询时,我都会截断Inspections_due表,因为添加到Inspections表的新跟进检查会使Inspections_due表中的某些结果不再有效。

第一次查询大约有9,000个结果。也许整体编写另一个查询以删除Inspections_due表中的无效结果并且每次运行此查询时仅将新记录添加到Inspections_due会更快。

注意:我尝试选择计数(*)而不是选择存在,但速度差异不大。

任何建议都会很棒!感谢

CREATE PROCEDURE create_due_inspections()
BEGIN

  DECLARE done INT DEFAULT FALSE;
  DECLARE iid int(10); #unique inspection id
  DECLARE sn VARCHAR(16); #serial number
  DECLARE dt date; #date_stamp
  DECLARE `result` int;

  DECLARE cur1 CURSOR FOR SELECT inspection_id, serial_number, date_stamp FROM 
      Inspections where type_due = '3' and inspection_completed is null;

  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  TRUNCATE TABLE `Inspections_due`; # clean out the old results

  OPEN cur1;

  read_loop: LOOP

    FETCH cur1 INTO iid,sn,dt;
    IF done THEN
      LEAVE read_loop;
    END IF;

    SET `result` := (select exists(Select inspection_id from Inspections
where serial_number = sn and date_stamp > dt and inspection_completed is not null));

    IF  `result` THEN
        insert into Inspections_due values(iid);
    END IF;

  END LOOP;

  CLOSE cur1;
END;

1 个答案:

答案 0 :(得分:1)

你应该避免光标并使用集

INSERT into Inspections_due 
SELECT 
      inspection_id as iid 
FROM 
      Inspections I1 
where 
      type_due = '3' and inspection_completed is null
      and exists(
           Select inspection_id 
           from Inspections I2
           where I2.serial_number = I1.serial_number 
                 and I2.date_stamp >  I1.date_stamp
                 and inspection_completed is not null))

同样通过内部联接替换存在子查询

SELECT distinct
      inspection_id as iid 
FROM 
      Inspections I1 
inner join  
      Inspections I2
         on
                 I2.serial_number = I1.serial_number 
                 and I2.date_stamp >  I1.date_stamp
                 and inspection_completed is not null