Php MySQL查询增强的性能取决于日期

Php MySQL查询增强的性能取决于日期,php,mysql,database,innodb,Php,Mysql,Database,Innodb,我有这个表,记录了从我的网站发送的短信 我想为每个用户计算一些数据,例如发送短信的数量和两个日期之间的短信数量之和,但当我执行查询时,需要花费20-30秒的时间才能完成,因为我有数百万条记录 这是我的mysql查询 Name Type Collation Null Default 1 sms_id int(7) None AUTO_INCREMENT 2 users_id

我有这个表,记录了从我的网站发送的短信 我想为每个用户计算一些数据,例如发送短信的数量和两个日期之间的短信数量之和,但当我执行查询时,需要花费20-30秒的时间才能完成,因为我有数百万条记录

这是我的mysql查询

Name  Type              Collation   Null    Default     
1     sms_id            int(7)      None    AUTO_INCREMENT  
2     users_id          int(5)      NULL    NULL    
3     sms_number        varchar(9)  No      None        
4     sms_amount        varchar(7)  No      None        
6     server_id         tinyint(2)  Yes     NULL        
7     sms_device        varchar(1)  No      None        
8     special_id        int(6)      Yes     NULL        
9     sms_ip            varchar(32) No      None        
10    sms_adddate       timestamp   No      CURRENT_TIMESTAMP   
主键:sms_id 外键:用户id、服务器id、专用id

我所有的表都是InnoDB引擎,我已经在它之间建立了关系

我能做些什么来加速这个查询?
将索引添加到sms\u amount和sms\u adddate或其他内容是错误的吗?

您的查询中有两个子查询,因此您在sms列表中行走了两倍。试着这样做,我认为应该花一半的时间:

select *,
(select count(sms_id) from sms where sms_adddate>11-11-2012 and sms_adddate<11-11-2013 and sms.users_id=users.users_id limit 1 ) as sms_count,
(select sum(sms_amount) from sms where
 sms_adddate>11-11-2012 and sms_adddate<11-11-2013 and
 sms.users_id=users.users_id limit 1) as sms_amount
 from users limit 10
此外,字段sms.sms\u adddate和sms.users\u id应该有它们的索引,以加速查询使用的过滤器


如果您还想看到在此期间没有短信的用户,可以使用左外连接而不是内连接。。。实际上,所有用户的索引都应该位于用于查找记录的列上。。。出现在where部分中的。所以,对于sms_adddate,是的,这是一个很好的想法,什么样的索引可以做。。如果在两列中加一行是好的,我可以单独做还是一起做。。我的意思是,对于每一列,我都会这样做,或者在同一个索引@naveed中一起做-hasan@hazem从这个查询判断,看起来您需要一个跨sms_adddate和user的多列索引_id@colin-莫雷利:添加多列索引还是单列索引正确?@hazem这取决于具体情况。如果您总是同时查询日期和用户,则多列索引可能会产生最佳性能。我复制了您的查询,但比我的查询花费的时间要长得多。您添加了sms_adddate索引吗?这是重要的编辑:另外sms.users\u id应该有一个索引,您可以在这里使用sms\u adddate。我没有这样做,我担心这个过程会花费很长时间,并且会影响到其他用户,因为有数百万条记录,这肯定会花费很长时间,尽管最后它会非常适合这个查询。您可以先在开发环境或类似的环境中使用DB的副本。我已经用索引和过滤器做了很多实验,我可以告诉你这两者之间有很大的区别。
SELECT users.*,
       COUNT(DISTINCT sms.sms_id) AS sms_count,
       SUM(sms.sms_amount) AS sms_amount
FROM users
     INNER JOIN sms
         ON users.users_id = sms.users_id
         AND sms.sms_adddate>11-11-2012 and sms.sms_adddate<11-11-2013
WHERE 1
GROUP BY users.users_id
# Optionally (extra time consumption): ORDER BY sms_count DESC
LIMIT 10;