简体   繁体   English

慢SQL查询,如何提高这个查询速度?

[英]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.我有一个表 (call_history) 与电话报告列表, caller_id 是来电者和 start_date (DATETIME) 是通话日期。 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; start_date 和 caller_id 列都有索引; 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)以下“WHERE SUBSTR(c2.start_date,1,10)”正在破坏您的索引(您不应在 where 子句的左侧执行函数)

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还重新阅读您的问题,我认为这是另一种不使用 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.您正在做一件奇怪的事情 - 在WHEREGROUPORDER子句中使用函数。 MySQL will never use indexes when function was applied to calculate condition.当函数用于计算条件时,MySQL永远不会使用索引。 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).所以,你不能用这个查询做任何事情,但为了改善你的情况,你应该改变你的表结构并将你的日期存储为DATE列(和单列)。 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好的,这是理想的解决方案,速度现在是 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 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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