[MDEV-5373] Optimize result from functions in SELECT Created: 2013-12-02  Updated: 2013-12-04  Due: 2014-01-03  Resolved: 2013-12-04

Status: Closed
Project: MariaDB Server
Component/s: None
Fix Version/s: None

Type: Task Priority: Minor
Reporter: Antonio Fernandes Assignee: Sergei Golubchik
Resolution: Not a Bug Votes: 0
Labels: optimizer


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



 Comments   
Comment by Antonio Fernandes [ 2013-12-03 ]

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

Comment by Sergei Golubchik [ 2013-12-03 ]

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.

Comment by Antonio Fernandes [ 2013-12-04 ]

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

Best regards,
Antonio

Generated at Thu Feb 08 07:03:46 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.