本帖最后由 default7 于 2013-09-03 10:46:03 编辑

解决方案 »

  1.   


    要遍历 表ratedat中的所有记录。但为了防止死机,对每次遍历数量我加了限制。
      

  2.   


    我对遍历开头和结尾作了限制。
    比如第10个分区,是从$idStart开始扫描。-- 得到这一区间的开始:id1
    SELECT MIN(trade_id) AS id1 FROM tb WHERE trade_id>=$idStart 
    -- 得到这一区间的结束:id2
    SELECT trade_id AS id2 FROM tb WHERE trade_id>=$idStart AND trade_id<$idStart+$ScanRange LIMIT $PerPartition-1,1
      

  3.   


    其实我是为了执行这一段SQL(涉及另外一个表 rate_buyer):    INSERT INTO rate_buyer(uid,costcount,costsum,costavg,costmax,costmin)
        SELECT uid_buy AS uid,
            COUNT(trade_id) AS costcount,
            SUM(goods_price) AS costsum,
            ROUND(AVG(goods_price),2) AS costavg,
            MAX(goods_price) AS costmax,
            MIN(goods_price) AS costmin
        FROM ratedat  
        GROUP BY uid_buy但是由于ratedat表有1亿多数据,太多了。所以才会用WHERE来限制每次存取的条数。
    就变成了如下:    SELECT uid_buy AS uid,
            COUNT(trade_id) AS costcount,
            SUM(goods_price) AS costsum,
            ROUND(AVG(goods_price),2) AS costavg,
            MAX(goods_price) AS costmax,
            MIN(goods_price) AS costmin
        FROM ratedat  WHERE trade_id BETWEEN $id1 AND $id2
        GROUP BY uid_buy$id1 和 $id2 就来自于ratedat_page 中的记录。现在发现生成ratedat_page真的太慢了。
    数据一多,以前经常用的老方法都失灵了一样。
      

  4.   

    我有3个建议可以参考:
    1.分区。按照trade_time分区,每年(或者每月,主要看你业务是年还是月)的数据是一个分区,按照id有点太多了些。
    2.把历史数据放到归档库中,估计热点数据也不会有很多,这样查询就会快很多!
    3.如果还是不行,新增汇总表之类的,把要查询的数据提前准备好,然后只对这个表查询,是不是好很多!
      

  5.   

    我想:uid_buy是有索引的,对吧?
      

  6.   

    更正:按照trade_time是不行的,因为你的查询中根本就没有用到trade_time条件!!!
      

  7.   

    看来必须要分区了!!!因为数据量太多,直接查,使用索引查都要扫描很多很多数据,从而产生很多随机IO。innodb一个表最多1024个分区,但一般不要大于100个分区,分区太多也会影响效率的。注意:
    1.分区后,where条件中一定要有分区列过滤,尽量筛选分区。
    2.各个分区可以放到不同的硬盘上,可以提高io效率。按照id分区:HASH(ID DIV 1000000),这将为100万数据建立一个分区。
      

  8.   

    你这不是正常操作,备份后在另一台机器跑吧。NoSQL对于这种大数据的操作可能性能会好些。