Mysql Bulk更新性能改进(当...案例时)

时间:2014-02-13 09:15:55

标签: mysql sql database-performance query-performance

我有一个这样的查询,应该在每个MySQL操作之后执行。此查询现在正在减慢页面加载速度,因为数据增加了,我做了所有事情,如正确的索引,但查询仍然相对较慢。

还有其他方法可以执行这些检查吗?

$query = "
UPDATE {$tprefix}wh_profg 
   SET status =
       CASE 
       WHEN 
          batchno in (
            select 
                batchno 
            from 
                {$tprefix}wh_profulldetail 
            where 
                remainingdays <= 0
          )
       THEN 
          'expired'

       WHEN 
          QC = 'rejected' and QA != 'rejected' 
            and status != 'expired' 
       THEN 
          'QC-rejected'

       WHEN 
          QA = 'rejected' and QC != 'rejected' 
            and status != 'expired' 
       THEN 
          'QA-rejected'

       WHEN 
          QA = 'rejected' and QC = 'rejected' 
            and status != 'expired' 
       THEN 
          'QA&QC-rejected'

       WHEN 
          (
            batchno in (
            select 
                batchno 
            from 
                {$tprefix}wh_profulldetail 
            where 
                available <= 0
            )
          ) and status != 'expired' 
            and status NOT LIKE '%rejected'
       THEN 
          'empty'

       WHEN 
          QC ='quarantine' and status != 'empty' 
          and status != 'expired' and 
          batchno in (
            select 
                batchno 
            from 
                {$tprefix}wh_profulldetail 
            where 
                available > 0 and remainingdays > 0
          )
       THEN 
          'quarantine'

       WHEN 
          QC ='approved' and QA = 'approved' 
          and status != 'empty' and status != 'expired' 
          and status NOT LIKE '%rejected' and 
          batchno in (
            select 
                batchno 
            from 
                {$tprefix}wh_profulldetail 
            where 
                available > 0 and remainingdays > 0
         )
       THEN 
          'available'
       ELSE
          'unknown'
       END
";

2 个答案:

答案 0 :(得分:3)

从澄清中,我认为你说wh_profulldetail是一个加入wh_profg和wh_profg_usage的视图。对wh_profg_usage的任何插入或更新都可能影响wh_profg.status。因此,您需要在wh_profg和wh_profg_usage上使用INSERT和UPDATE触发器。

创建触发器后,删除原始UPDATE查询。更新将在需要时由触发器执行。此外,更新将仅在受影响的一个wh_profg行上执行。这应该可以消除您的性能问题,因为您当前的更新查询正在更新wh_profg中的每一行。

触发器看起来像:

DELIMITER //
CREATE TRIGGER insert_wh_profg_usage AFTER INSERT ON wh_profg_usage
   FOR EACH ROW
      UPDATE wh_profg a SET status = status WHERE batchno = NEW.batchno;
//

CREATE TRIGGER update_wh_profg_usage AFTER UPDATE ON wh_profg_usage
   FOR EACH ROW
      UPDATE wh_profg a SET status = status WHERE batchno = NEW.batchno;
//

CREATE TRIGGER update_wh_profg_usage AFTER DELETE ON wh_profg_usage
   FOR EACH ROW
      UPDATE wh_profg a SET status = status WHERE batchno = NEW.batchno;
//

CREATE TRIGGER insert_wh_profg BEFORE INSERT ON wh_profg
   FOR EACH ROW
   BEGIN

      SELECT 1
            ,remainingdays
            ,available
        INTO @detailfound
            ,@remainingdays
            ,@available
        FROM wh_profulldetail
       WHERE batchno = NEW.batchno;

      IF @remainingdays <= 0
      THEN SET NEW.status = 'expired';

      ELSEIF NEW.qc  = 'rejected'
         AND NEW.qa != 'rejected'
         AND new.status != 'expired'
        THEN SET NEW.status = 'QC-rejected';

      ELSEIF NEW.qa  = 'rejected'
         AND NEW.qc != 'rejected'
         AND new.status != 'expired'
        THEN SET NEW.status = 'QA-rejected';

      ELSEIF NEW.qa = 'rejected'
         AND NEW.qc = 'rejected'
         AND new.status != 'expired'
        THEN SET NEW.status = 'QA&QC-rejected';

      ELSEIF NEW.status != 'expired'
         AND NEW.status NOT LIKE '%rejected'
         AND @detailfound = 1
         AND @remainingdays <= 0
        THEN SET NEW.status = 'empty';

      ELSEIF NEW.qc ='quarantine'
         AND NEW.status != 'empty'
         AND NEW.status != 'expired'
         AND @detailfound = 1
         AND @available > 0
         AND @remainingdays > 0
        THEN SET NEW.status = 'quarantine';

      ELSEIF NEW.qc = 'approved'
         AND NEW.qa = 'approved'
         AND NEW.status != 'empty'
         AND NEW.status != 'expired'
         AND NEW.status NOT LIKE '%rejected'
         AND @detailfound = 1
         AND @available > 0
         AND @remainingdays > 0
        THEN SET NEW.status = 'available';

      ELSE SET NEW.status = 'unknown';

      END IF;

   END;
//

CREATE TRIGGER update_wh_profg BEFORE UPDATE ON wh_profg
   FOR EACH ROW
   BEGIN

      SELECT 1
            ,remainingdays
            ,available
        INTO @detailfound
            ,@remainingdays
            ,@available
        FROM wh_profulldetail
       WHERE batchno = NEW.batchno;

      IF @remainingdays <= 0
      THEN SET NEW.status = 'expired';

      ELSEIF NEW.qc  = 'rejected'
         AND NEW.qa != 'rejected'
         AND new.status != 'expired'
        THEN SET NEW.status = 'QC-rejected';

      ELSEIF NEW.qa  = 'rejected'
         AND NEW.qc != 'rejected'
         AND new.status != 'expired'
        THEN SET NEW.status = 'QA-rejected';

      ELSEIF NEW.qa = 'rejected'
         AND NEW.qc = 'rejected'
         AND new.status != 'expired'
        THEN SET NEW.status = 'QA&QC-rejected';

      ELSEIF NEW.status != 'expired'
         AND NEW.status NOT LIKE '%rejected'
         AND @detailfound = 1
         AND @remainingdays <= 0
        THEN SET NEW.status = 'empty';

      ELSEIF NEW.qc ='quarantine'
         AND NEW.status != 'empty'
         AND NEW.status != 'expired'
         AND @detailfound = 1
         AND @available > 0
         AND @remainingdays > 0
        THEN SET NEW.status = 'quarantine';

      ELSEIF NEW.qc = 'approved'
         AND NEW.qa = 'approved'
         AND NEW.status != 'empty'
         AND NEW.status != 'expired'
         AND NEW.status NOT LIKE '%rejected'
         AND @detailfound = 1
         AND @available > 0
         AND @remainingdays > 0
        THEN SET NEW.status = 'available';

      ELSE SET NEW.status = 'unknown';

      END IF;

   END;
//


delimiter ;

如果没有表格结构或样本数据或wh_profulldetail视图,完全指出这一点非常困难。

答案 1 :(得分:0)

wh_profg与wh_profulldetail之间是否存在一对一的关系?

如果是这样的话,类似于Endre上面的解决方案,但只是进行普通连接而不是针对子查询的连接。

UPDATE {$tprefix}wh_profg a
LEFT OUTER JOIN {$tprefix}wh_profulldetail b
ON a.batchno = b.batchno
SET a.status =
    CASE 
        WHEN b.batchno IS NOT NULL AND b.remainingdays <= 0
            THEN 'expired'
        WHEN a.QC = 'rejected' and a.QA != 'rejected' and a.status != 'expired' 
            THEN 'QC-rejected'
        WHEN a.QA = 'rejected' and a.QC != 'rejected' and a.status != 'expired' 
            THEN 'QA-rejected'
        WHEN a.QA = 'rejected' and a.QC = 'rejected' and a.status != 'expired' 
            THEN 'QA&QC-rejected'
        WHEN b.batchno IS NOT NULL AND b.available <= 0 and a.status != 'expired' and a.status NOT LIKE '%rejected'
            THEN 'empty'
        WHEN a.QC ='quarantine' and a.status != 'empty' and a.status != 'expired' and b.batchno IS NOT NULL AND b.available > 0 and b.remainingdays > 0
            THEN 'quarantine'
        WHEN a.QC ='approved' and a.QA = 'approved' and a.status != 'empty' a.and status != 'expired' a.and status NOT LIKE '%rejected' and b.batchno IS NOT NULL AND available > 0 and remainingdays > 0
            THEN 'available'
            ELSE 'unknown'
    END