Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-5373

Optimize result from functions in SELECT

    Details

    • Type: Task
    • Status: Closed
    • Priority: Minor
    • Resolution: Not a Bug
    • Fix Version/s: None
    • Component/s: None
    • Labels:

      Description

      I've wrote a function to add/subtract 'our' working days from a date:

      CREATE DEFINER=`root`@`localhost` FUNCTION `DATEADD_BUSINESSDAYS`(`begin_date` DATE, `num_days` INT)
      	RETURNS date
      	LANGUAGE SQL
      	NOT DETERMINISTIC
      	READS SQL DATA
      	SQL SECURITY INVOKER
      	COMMENT 'Test function.... not yet in production'
      BEGIN
      	DECLARE i, j INT;
      	IF (num_days = 0) THEN
      		RETURN begin_date;
      	END IF;
      
      	SET i = 0;
      	SET j = 0;
      	IF (num_days > 0) THEN
      		WHILE i < num_days DO
      			SET i = i + 1;
      			SET j = j + 1;
      			WHILE 
      				DAYOFWEEK(DATE_ADD(begin_date, INTERVAL j DAY)) IN (1,7)
      				OR (SELECT 1 FROM holidays WHERE hDate = DATE_ADD(begin_date, INTERVAL j DAY))
      			DO
      				BEGIN
      					SET j = j + 1;
      				END;
      			END WHILE;
      		END WHILE;
      	ELSE
      		WHILE i > num_days DO
      			SET i = i - 1;
      			SET j = j - 1;
      			WHILE 
      				DAYOFWEEK(DATE_ADD(begin_date, INTERVAL j DAY)) IN (1,7)
      				OR (SELECT 1 FROM holidays WHERE hDate = DATE_ADD(begin_date, INTERVAL j DAY))
      			DO
      				BEGIN
      					SET j = j - 1;
      				END;
      			END WHILE;
      		END WHILE;
      	END IF;
      
      	RETURN DATE_ADD(begin_date, INTERVAL j DAY);
      END
      

      Explain without function use:

      EXPLAIN
      SELECT
      	xxxx
      FROM
      	invoices fac
      	INNER JOIN details det ON fac.Invoice = det.Invoice
      WHERE
      	fac.`Data` = CURDATE()-1
      	AND fac.Invoice LIKE 'PVD%'
      	AND fac.Route IN ('038','205','211')
      GROUP BY
      	fac.Client,
      	fac.DeliveryID
      

      returns

      +------+-------------+-------+------+---------------+---------+---------+---------------------+------+----------------------------------------------------+
      | id   | select_type | table | type | possible_keys | key     | key_len | ref                 | rows | Extra                                              |
      +------+-------------+-------+------+---------------+---------+---------+---------------------+------+----------------------------------------------------+
      |    1 | SIMPLE      | fac   | ref  | PRIMARY,Data  | Data    | 4       | const               |    1 | Using index condition; Using where; Using filesort |
      |    1 | SIMPLE      | det   | ref  | Invoice       | Invoice | 48      | xxxxxxx.fac.Invoice |    3 |                                                    |
      +------+-------------+-------+------+---------------+---------+---------+---------------------+------+----------------------------------------------------+
      

      With function use:

      EXPLAIN
      SELECT
      	xxxx
      FROM
      	invoices fac
      	INNER JOIN details det ON fac.Invoice = det.Invoice
      WHERE
      	fac.`Data` = DATEADD_BUSINESSDAYS(CURDATE(),-1)
      	AND fac.Invoice LIKE 'PVD%'
      	AND fac.Route IN ('038','205','211')
      GROUP BY
      	fac.Client,
      	fac.DeliveryID
      

      returns

      +------+-------------+-------+-------+---------------+---------+---------+---------------------+--------+----------------------------------------------------+
      | id   | select_type | table | type  | possible_keys | key     | key_len | ref                 | rows   | Extra                                              |
      +------+-------------+-------+-------+---------------+---------+---------+---------------------+--------+----------------------------------------------------+
      |    1 | SIMPLE      | fac   | range | PRIMARY       | PRIMARY | 47      | NULL                | 215090 | Using index condition; Using where; Using filesort |
      |    1 | SIMPLE      | det   | ref   | Invoice       | Invoice | 48      | xxxxxxx.fac.Invoice |      3 | Using where                                        |
      +------+-------------+-------+-------+---------------+---------+---------+---------------------+--------+----------------------------------------------------+
      

      Is there any way to optimize this type of queries (with function use in 'where')?

        Gliffy Diagrams

          Attachments

            Issue Links

              Activity

              Hide
              ampf Antonio Fernandes added a comment -

              Btw, I could use a workaround

              SET @v_date = DATEADD_BUSINESSDAYS(CURDATE(), -1);
              

              and the use the variable in the query... but I would miss the point of improving the optimizer...

              Best regards

              Show
              ampf Antonio Fernandes added a comment - Btw, I could use a workaround SET @v_date = DATEADD_BUSINESSDAYS(CURDATE(), -1); and the use the variable in the query... but I would miss the point of improving the optimizer... Best regards
              Hide
              serg Sergei Golubchik added a comment -

              Declare your function DETERMINISTIC. Currently it is not, and optimizer cannot make any assumptions about it. Optimizer cannot optimize invocations of the non-deterministic function.

              Show
              serg Sergei Golubchik added a comment - Declare your function DETERMINISTIC. Currently it is not, and optimizer cannot make any assumptions about it. Optimizer cannot optimize invocations of the non-deterministic function.
              Hide
              ampf Antonio Fernandes added a comment -

              My bad... I should've check for prior "bug" reports...please close it...

              Best regards,
              Antonio

              Show
              ampf Antonio Fernandes added a comment - My bad... I should've check for prior "bug" reports...please close it... Best regards, Antonio

                People

                • Assignee:
                  serg Sergei Golubchik
                  Reporter:
                  ampf Antonio Fernandes
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  2 Start watching this issue

                  Dates

                  • Due:
                    Created:
                    Updated:
                    Resolved:

                    Time Tracking

                    Estimated:
                    Original Estimate - Not Specified
                    Not Specified
                    Remaining:
                    Remaining Estimate - 0 minutes
                    0m
                    Logged:
                    Time Spent - 5 minutes
                    5m