简体   繁体   中英

Slow SQL Query, how to improve this query speed?

I have a table (call_history) with a list of phone calls report, caller_id is the caller and start_date (DATETIME) is the call date. I need to make a report that will show how many people called for the first time for every day. For example:

2013-01-01 - 100
2013-01-02 - 80
2013-01-03 - 90

I have this query that does it perfectly, but it is very slow. There are indexes on both start_date and caller_id columns; is there an alternative way to get this information to speed the process up?

Here is the query:

SELECT SUBSTR(c1.start_date,1,10), COUNT(DISTINCT caller_id)
FROM call_history c1
WHERE NOT EXISTS
 (SELECT id
 FROM call_history c2
 WHERE SUBSTR(c2.start_date,1,10) < SUBSTR(c1.start_date,1,10) 
   AND c2.caller_id=c1.caller_id)
GROUP BY SUBSTR(start_date,1,10)
ORDER BY  SUBSTR(start_date,1,10) desc

The following "WHERE SUBSTR(c2.start_date,1,10)" is breaking your index (you shouldn't perform functions on the left hand side of a where clause)

Try the following instead:

SELECT DATE(c1.start_date), COUNT(caller_id) 
FROM call_history c1 
    LEFT OUTER JOIN call_history c2 on c1.caller_id = c2.caller_id and c2.start_date < c1.start_date 
where c2.id is null 
GROUP BY DATE(start_date) 
ORDER BY start_date desc 

Also re-reading your problem, I think this is another way of writing without using NOT EXISTS

SELECT DATE(c1.start_date), COUNT(DISTINCT c1.caller_id) 
FROM call_history c1 
where start_date = 
    (select min(start_date) from call_history c2 where c2.caller_id = c1.caller_id) 
GROUP BY DATE(start_date) 
ORDER BY c1.start_date desc;

You are doing a weird thing - using functions in WHERE , GROUP and ORDER clauses. MySQL will never use indexes when function was applied to calculate condition. So, you can not do anything with this query, but to improve your situation, you should alter your table structure and store your date as DATE column (and single column). Then create index by this column - after this you'll get much better results.

尝试用左外连接替换 NOT EXISTS。

OK here is the ideal solution, speed is now 0.01

SELECT first_call_date, COUNT(caller_id) AS caller_count
FROM (
    SELECT caller_id, DATE(MIN(start_date)) AS first_call_date
    FROM call_history 
    GROUP BY caller_id
) AS ch
GROUP BY first_call_date
ORDER BY first_call_date DESC 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM