Mysql – Procedure MySQL cursor taking a long time to execute

cursorsMySQLmysql-5.7optimizationstored-procedures

I have a MySQL procedure, with a cursor in it. The sample cursor query is given below

DECLARE cs CURSOR FOR
           (SELECT  a.mag_id FROM A a  WHERE
                a.creation_date BETWEEN (v_fromdate) AND (v_todate) 
                AND a.type_id IN (SELECT type_id FROM key2 WHERE   sessionId=v_sessionId)
                AND a.mag_id IN (SELECT magid FROM    key1 WHERE   sessionId=v_sessionId order by magid)
                )
     UNION
                (SELECT  b.combo_mag_id FROM B b 
                WHERE
                b.creation_date BETWEEN (v_fromdate) AND (v_todate) 
                AND b.type_id IN (SELECT type_id FROM    key2 WHERE   sessionId=v_sessionId)
                AND b.combo_mag_id IN (SELECT magid FROM    key1 WHERE   sessionId=v_sessionId order by magid)
                );

DECLARE
CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
SET v_cur_time = now();
SET v_cur_query = 'cursor';
OPEN cs;
SELECT timestampdiff(SECOND,v_cur_time,now()) into v_diff;
SELECT CONCAT('Current Query: ', v_cur_query, ' Time taken: ', v_diff); 

Both table A and B have millions of records.I have partitions created in both the tables with partition by range on creation_date.For 3 months of a date range the cursor takes almost 4 mins to execute.But when i tried running the same query in MySQL workbench editor,by setting the parameters for the same date range it took only 22 seconds. Can somebody tell me why it executes faster in an SQL editor, and since i have to use it in the stored procedure, is there any way to optimize it ??

Best Answer

  • IN ( SELECT ... ) is often poorly optimized. See if you can turn it into either a JOIN or EXISTS ( SELECT 1 ... )
  • Don't use a CURSOR if it is possible to write a JOIN or something to do the entire task rather than acting one row at a time.
  • PARTITIONing is unlikely to be beneficial; let's see the details. (Composite indexes often do the job adequately.)
  • Remove the ORDER BY in subqueries; it has no effect. If you need ordering, please elaborate; we should be able to find another way.
  • Are there parameters being fed in? Which?