I had a query like this, that should be executed after each MySQL actions. This query is now slowing down page loading because the data increased, I did everything like proper indexing, but the query is still slow relatively.
Is there any other way to perform those checks?
$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
";
Another way to get fast updates is to delay updates and then do many updates in a row later. Performing multiple updates together is much quicker than doing one at a time if you lock the table. For a MyISAM table that uses dynamic row format, updating a row to a longer total length may split the row.
From the clarifications, I think you are saying that wh_profulldetail is a view that joins wh_profg and wh_profg_usage. Any inserts or updates to wh_profg_usage could affect wh_profg.status. Consequently, you will need INSERT and UPDATE triggers on both wh_profg and wh_profg_usage.
Once the triggers have been created, eliminate your original UPDATE query. The update will be performed by the triggers when needed. In addition, the update will only be performed on the one wh_profg row that is affected. This should eliminate your performance issues because your current update query is updating EVERY row in wh_profg.
The triggers would look something like:
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 ;
Without table structures or sample data or wh_profulldetail view, it's pretty tough to completely nail this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With