centos5.6
mysql5.1
在线某千万大表display(id,userid,.....)
其中 id是自增长主键
SELECT userid,COUNT(DISTINCT(`id`)) as `ipnum` FROM `data`.`display` WHERE `uid`='10111' AND `advid` LIKE '%1000%' AND `type`='link' AND `time` BETWEEN '2011-09-01 00:00:00' AND '2011-10-01 00:59:59' group by date(time),userid
这个sql统计某个月 各个用户的总登录次数?这个sql实际使用发现很慢。 假如索引都成功建立。
这个sql 该如何进行优化?
oltp在线不会进行表分区。
思考优化方式如下
1 使用视图 把每个月所需字段单独从主表提出来做成一个视图 之后进行汇总?
2 使用no-sql把这个表cache起来 用java程序处理或者用memcache来处理?
    是否可行
             

解决方案 »

  1.   

    -- 既然id是自增长主键,为什么还要去count(distinct `id`)呢?
      

  2.   


    -- distinct 关键字完全可以不要了嘛:你已经知道id字段,
    -- 在整个表记录中,是非空、唯一(主键的一个重要特性:非空且唯一),
    -- 还去用 distinct 去除重复,不是明摆着想让你的查询多做无用功嘛!
      

  3.   

    sorry 回忆这个题目搞混了 
    (应该是先后的2个问题
    第1个问题是 count(id)
    第2个问题是 COUNT(DISTINCT(`id`))
    )第一个问题完整描述如下
    SELECT userid,COUNT(`userid`)) as `ipnum` FROM `data`.`display` WHERE `uid`='10111' AND `advid` LIKE '%1000%' AND `type`='link' AND `time` BETWEEN '2011-09-01 00:00:00' AND '2011-10-01 00:59:59' group by date(time),userid
    这个sql应该是 统计某月 每个用户的总登录次数, 如果
    用户userid=501
    userid  ip
    501     10.0.1.1
    501     10.0.1.2
    501     10.0.1.3
    501     10.0.1.4
    501     10.0.1.5
    502     10.0.1.1
    ......       可以不考虑自增长id, 日期都是某同一天
    这个简单,直接在并发在线表执行就可以了第2个问题是讨论某天的有多少不同的用户访问
    SELECT date(time),COUNT(DISTINCT(`useid`)) as `ipnum` FROM `data`.`display` WHERE `uid`='10111' AND `advid` LIKE '%1000%' AND `type`='link' AND `time` BETWEEN '2011-09-01 00:00:00' AND '2011-10-01 00:59:59' group by date(time)
      

  4.   

    1、为什么oltp在线就不能分区,完全可以不停应用就搞定的。2、你的这个千万级别的表,保存的数据是多久的?真正一个月内的登录记录有多少?