简体   繁体   English

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

[英]MySQL Stored Procedure for Complex Query takes 5 minutes

This procedure is working but it takes 5 minutes to run. 此过程正在运行,但是需要5分钟才能运行。 Is there a faster, simpler way? 有没有更快,更简单的方法?

I have one table that contains a list of inspections. 我有一张表,其中包含检查清单。 There are follow up inspections inserted at a later date into the same table. 以后在同一表中插入了后续检查。 The follow up inspections have the same serial_number but a different date_stamp. 后续检查具有相同的序列号,但具有不同的date_stamp。 I need to find out which inspections do not have completed follow up inspections. 我需要找出哪些检查尚未完成跟进检查。

So first I'm getting all the serial_numbers that are of type_due=3 and are not marked as inspection_completed. 所以首先我要获取所有type_due = 3且未标记为inspection_completed的序列号。

Then, from this list of serial_numbers, I am checking if there is an inspection with the same serial_number at a later date_stamp that is marked as inspection_completed. 然后,从该序列号列表中,我正在检查是否在以后的date_stamp上进行了具有相同序列号的检查,该检查被标记为inspection_completed。

So it is a select only if something else exists; 因此,只有在存在其他条件时才是选择。 an elimination of the pool of results in the first query if there is a result in the second query with the same serial_number, greater date, and an inspection_completed value that is not null. 如果第二个查询中的结果具有相同的serial_number,更大的日期和Inspection_completed值不为null,则消除第一个查询中的结果池。

I am truncating the Inspections_due table each time this query is run because new follow up inspections that are added to the Inspections table will make some results in the Inspections_due table no longer valid. 每次运行此查询时,我都会截断Inspections_due表,因为添加到Inspections表中的新的后续检查将使Inspections_due表中的某些结果不再有效。

There are about 9,000 results from the first query. 第一个查询大约有9,000个结果。 Maybe it would be faster overall to write another query to remove invalid results in the Inspections_due table and only add the new records to Inspections_due each time this query is run. 总体而言,编写另一个查询以删除Inspections_due表中的无效结果,并且每次运行此查询时仅将新记录添加到Inspections_due可能总体上更快。

Note: I tried Select count(*) instead of Select Exists, but not much speed difference. 注意:我尝试使用Select count(*)代替Select Exists,但是速度差异不大。

Any suggestions would be great! 任何建议都很好! Thanks 谢谢

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;

You should avoid cursor and work with sets : 您应该避免使用游标并使用set

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))

Also replace exists subquery by a inner join : 还可以通过内部联接替换现有子查询

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM