昨天得到一个慢查询的解决思路,今天又找了一个困扰更长时间的sql
mysql 在linux 下 版本5.0以上 
当SessionLog 数量小的左右的时候,这个sql 执行时间速度还可以的 
select  count(distinct(ul.userId)) number,      
CASE        WHEN ul.lastaccess>curdate() THEN 1     
WHEN (ul.lastaccess>subdate(curdate(),1) and ul.lastaccess<curdate()) THEN 2          
WHEN (ul.lastaccess>date_Sub(curdate(), INTERVAL DAYOFMONTH(curdate())-1 day)) THEN 3     
 WHEN (ul.lastaccess>date_sub(date_Sub(curdate(), INTERVAL DAYOFMONTH(curdate())-1 day),INTERVAL 1 month) and ul.lastaccess<DATE_SUB(sysdate(),INTERVAL 1 month)) THEN 4        
 ELSE 5  END as Interval from  SessionLog ul,User u  where   u.id = ul.userid group by Interval;
但是现在几个月来,SessionLog 增长到300万,发现慢,高达43秒,实在是太慢。  而且这个表几乎每天必用,一天用好多次的。 
我已经对这个表加了索引 ,问该如何才能提升sql的速度?? 我在按照昨天的方法进行加临时表 用union all联合进行查询加快查询速度。
但是count(distinct  感觉改写难度要大很多?

解决方案 »

  1.   

    有点困惑 count(distinct(ul.userId)) WHEN (ul.lastaccess>subdate(curdate(),1) and ul.lastaccess <curdate()) THEN  等
    还是头疼不知道如何转化?
      

  2.   

    你要统计的不过是本日,昨日,本月,上月
    有多少不同名的用户登录。你每天晚上定时 12:00am 生成这个数据 (昨日上月)
    然后只需要统计今天本月的就行了!建议基于 lastaccess  的索引select 
    (select count(distinct userid) from SessionLog where lastaccess>=curdate()) as `number`,
    1 as `Interval`
    union all
    select 
    (select count(distinct userid) from SessionLog where lastaccess>=select curdate()-INTERVAL (day(curdate())-1) day ) as `number`,
    3 as `Interval`
    union all
    select * from xxxxxxxxxx
      

  3.   

    明白了 大致写如下select  count(distinct(ul.userId)) number,      
    CASE        WHEN ul.lastaccess>curdate() THEN 1    
    WHEN (ul.lastaccess>subdate(curdate(),1) and ul.lastaccess <curdate()) THEN 2          
    WHEN (ul.lastaccess>date_Sub(curdate(), INTERVAL DAYOFMONTH(curdate())-1 day)) THEN 3    
    WHEN (ul.lastaccess>date_sub(date_Sub(curdate(), INTERVAL DAYOFMONTH(curdate())-1 day),INTERVAL 1 month) and ul.lastaccess <DATE_SUB(sysdate(),INTERVAL 1 month)) THEN 4        
    ELSE 5  END as Interval from  SessionLog ul,User u  where  u.id = ul.userid 
    and ul.lastaccess<'2009-11-01'union all
    select  count(distinct(ul.userId)) number,      
    CASE        WHEN ul.lastaccess>curdate() THEN 1    
    WHEN (ul.lastaccess>subdate(curdate(),1) and ul.lastaccess <curdate()) THEN 2          
    WHEN (ul.lastaccess>date_Sub(curdate(), INTERVAL DAYOFMONTH(curdate())-1 day)) THEN 3    
    WHEN (ul.lastaccess>date_sub(date_Sub(curdate(), INTERVAL DAYOFMONTH(curdate())-1 day),INTERVAL 1 month) and ul.lastaccess <DATE_SUB(sysdate(),INTERVAL 1 month)) THEN 4        
    ELSE 5  END as Interval from  SessionLog ul,User u  where  u.id = ul.userid 
    and ul.lastaccess>'2009-11-01 00:00:00'group by Interval解决  感谢 楼上
      

  4.   

    上面的语句测试是ok的 count(distinct  可以替换为  group by id
    数据库设计其实可以改写的哦  (但项目已经上线 不要随便更改)