Optimise Date Related query with Create Dates
I have below query that takes about 9.8 seconds, I like to know is there a way to optimize the query with indexes,
I already have an index on 'uc.recieved_date'
other than this I don't what else I can do to optimize the SQL selection, There is no way to break it down to smaller portions with LIMIT as it's a graph.
SELECT (count(*)-1) AS total, a.Date AS created_dates
FROM
(
SELECT (CURDATE() - INTERVAL c.number DAY) AS date
FROM (SELECT singles + tens + hundreds number FROM
( SELECT 0 singles
UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) singles JOIN
(SELECT 0 tens
UNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30
UNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60
UNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90
) tens JOIN
(SELECT 0 hundreds
UNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300
UNION ALL SELECT 400 UNION ALL SELECT 500 UNION ALL SELECT 600
UNION ALL SELECT 700 UNION ALL SELECT 800 UNION ALL SELECT 900
) hundreds
ORDER BY number DESC) c
WHERE c.number BETWEEN 0 and 364
) a
LEFT OUTER JOIN `usr_count` uc
ON DATE(uc.received_on) = a.Date
WHERE
a.Date BETWEEN CURDATE() - INTERVAL 28 DAY AND CURDATE() GROUP BY a.Date
ORDER BY a.Date ASC
-
Build a permanent table of "numbers". (The 'cross-join' you have takes some time.)
-
Have
PRIMARY KEY(number)
on that table. (Needed for theWHERE
andORDER BY
) -
Consider switching to MariaDB, which has the pseudo table
seq_0_to_999
to provide "numbers" instantly. -
Since you have a
LEFT JOIN
, don't you needAND ... IS [NOT] NULL
? (Else make itINNER JOIN
.) -
ON DATE(uc.received_on) = a.Date
may be terribly inefficient. (See "sargable".) A possible fix isON uc.received_on >= a.Date AND uc.received_on < a.Date + INTERVAL 1 DAY
Do some of those, then come back for more suggestions.