Reputation: 1350
I have a stored procedure which runs pretty slow (6 sec) using the following JOIN:
JOIN tariffs t ON
(LEFT(`cdrs`.`cnumber`,7) = t.numberrange
OR LEFT(`cdrs`.`cnumber`,8) = t.numberrange)
Without the above JOIN the query runs at 1.5 sec. Any way how to improve the performance? Full stored procedure below:
CREATE DEFINER=`xxx`@`%` PROCEDURE `GetHourStats`(IN _ID INT, IN _YEAR INT, IN _MONTH INT, IN _DAY INT)
BEGIN
set @_START = UNIX_TIMESTAMP(date(_YEAR * 10000 + _MONTH * 100 + _DAY * 1));
set @_END = UNIX_TIMESTAMP(date_add(date(_YEAR * 10000 + _MONTH * 100 + _DAY * 1), interval 1 day));
SELECT h.idhour, h.`hour` as 'hour', innumber, count(*) as `count`, sum(talktime) as `duration` FROM (
SELECT
`cdrs`.`dcustomer` AS `dcustomer`,
(CASE
WHEN (LEFT(`cdrs`.`cnumber`, 2) = "01" OR LEFT(`cdrs`.`cnumber`, 2) = "02") THEN '01-02'
WHEN (LEFT(`cdrs`.`cnumber`, 2) = "03") THEN '03'
WHEN (LEFT(`cdrs`.`cnumber`, 2) = "05") THEN '05'
WHEN (LEFT(`cdrs`.`cnumber`, 2) = "06") THEN '06'
WHEN (LEFT(`cdrs`.`cnumber`, 2) = "07") THEN '07'
WHEN (LEFT(`cdrs`.`cnumber`, 3) = "080") THEN '080'
WHEN (LEFT(`cdrs`.`cnumber`, 3) = "084") THEN '084'
WHEN (LEFT(`cdrs`.`cnumber`, 3) = "087") THEN '087'
WHEN (LEFT(`cdrs`.`cnumber`, 2) = "09") THEN '09'
END) AS 'innumber',
FROM_UNIXTIME(`cdrs`.`start`) AS `start`,
(`cdrs`.`end` - `cdrs`.`start`) AS `duration`,
`cdrs`.`cnumber` AS `calling`,
`cdrs`.`talktime` AS `talktime`
FROM `cdrs`
JOIN tariffs t ON (LEFT(`cdrs`.`cnumber`,7) = t.numberrange OR LEFT(`cdrs`.`cnumber`,8) = t.numberrange)
WHERE `cdrs`.`start` >= @_START and `cdrs`.`start` < @_END
AND `cdrs`.`stype` = _LATIN1'external'
AND `cdrs`.`talktime` >= 5
AND `cdrs`.`status` = 'answer'
AND CHAR_LENGTH(`cdrs`.`cnumber`) = 11
GROUP BY callid
) cdr
JOIN customers c ON c.id = cdr.dcustomer
LEFT JOIN hub.hours h ON HOUR(cdr.`start`) = h.idhour
WHERE (c.parent = _ID or cdr.dcustomer = _ID or c.parent IN
(SELECT id FROM customers WHERE parent = _ID))
GROUP BY h.idhour, cdr.innumber
ORDER BY h.idhour;
END
Q: How can I make the above stored procedure run faster?
Upvotes: 0
Views: 57
Reputation: 142278
JOIN tariffs t ON
(LEFT(`cdrs`.`cnumber`,7) = t.numberrange
OR LEFT(`cdrs`.`cnumber`,8) = t.numberrange)
This might give you the same set:
JOIN tariffs t
ON cdrs.cnumber LIKE CONCAT(t.numberrange, '%')
It fails if numberrange is not 7 or 8 characters long, but perhaps that 'cannot' happen. Perhaps adding this somewhere would take care of that:
AND LENGTH(t.numberrange) BETWEEN 7 AND 8
INDEX(numberrange) -- no longer useful
INDEX(cnumber) -- may be useful here.
Upvotes: 1