有一张千万条记录的表CREATE TABLE `tb_trans` (
  `sid`        int(11)      NOT NULL auto_increment,
  `MerchId`    char(15)     NOT NULL,
  `TermId`     char(8)      NOT NULL,
  `TransDate`  date         NOT NULL,
  `TransTime`  Time         NOT NULL,
  `AccNo`      varchar(19)  NOT NULL,
  `Amount`     decimal(9,2) NOT NULL,
  `Charge`     decimal(9,2) default NULL,
  PRIMARY KEY  (`sid`,`MerchId`,`TermId`,`TransDate`,`TransTime`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8-- 每天需要update更新2万条Charge,大概1小时才能全部完成,类似一条条如下的语句:
UPDATE tb_trans SET Charge=0.51 WHERE sid=143 AND MerchId="12345678" AND TermId="123456" AND TransDate=20130101 AND TransTime=080101 AND AccNo="123" ;1、怎么样去更新能够比较快,还是在表结构上做什么修改?
2、我目前在系统里添加脚本自动去执行更新,采用 同时3个进程调用存储过程,去一条条更新。
多进程操作更新会快还是慢?还是一个进程一条条去更新更好?3、大师们还有其它的思路指导一下吗?新手求指教,谢谢

解决方案 »

  1.   

    首先对你这条更新语句有点疑问:UPDATE tb_trans SET Charge=0.51 WHERE sid=143 AND MerchId="12345678" AND TermId="123456sid 是自增字段,因此完全可以确认唯一一条记录,为何后面还跟了另外的几个条件。
      

  2.   

    create index xxx on tb_trans (`sid`,`MerchId`,`TermId`,`TransDate`,`TransTime`,AccNo)
      

  3.   

    虽然sid是自增,但是我将更新的每条记录中没有sid字段的值,所以必须用三四个字段保证唯一性。
      

  4.   

    首先,不说速度的问题,你这个数据表的设计存在很大的问题:1,如果能够确定唯一性,那么本不需要自增字段(sid)。
    2,MerchId和TermId 需要作为主键,为什么要用char类型?可以用其他类型代替吗?
    3,TransDate 和TransTime 可以用unix time 的整数来代替呢?date time 在遇到时区的时候,转换就够痛苦的了!
    4.`Amount`和Charge 用  decimal(9,2) 你没有指定符号,那么数据的精度并不高,不知道用int可以代替吗? int/100  应该可以表示两位数的精度了吗?话说回来,decimal在内存是是以字符串表示的!
    5.Charge default null 除非你要用NULL来作为条件查询,请另指定一个默认值!
    6,关于PRIMARY KEY的问题,你指定了自增字段,那么其他字段就用普通索引就好了!索引和更新就是一对冤家!!你都能确定唯一性了!说到加快速度,可以用如下方法:
    1,增加一个字段为保存这几个字段值连接在一起的hash,并以这个字段作为主键!前提是你需要保证这个的唯一性!
    2,存在hash或其他可以确定唯一性东西就可以横向拆分数据表了(你懂的)!
    2,推迟更改,将多条更新语句写为一条更新语句(这个你懂的);
    3,你的是MyISAM表,这么大的表且常更新,在每次更新后OPTIMIZE TABLE大家拍砖(轻)!!
      

  5.   

    create index xxx on tb_trans (`sid`,`MerchId`,`TermId`,`TransDate`,`TransTime`,AccNo)建议将`TransDate`,`TransTime`合并为1个字段
    UNIX_TIMESTAMP(), FROM_UNIXTIME()处理
      

  6.   

    首先,感谢各位前辈的指点。
    TO: mianyangone 1、我删除了自增字段,确实不需要。
    2、MerchId和TermId不需要做主键,现在只在上面做索引了。
    3、date time 在遇到时区转换,这个问题,不太明白,不过我应该不会用的到。
    4、Amount和Charge消费金额和手续费,精确2位小数,只供查询使用。我不太清楚如果使用 int/100 会有什么好处?
    5、Charge default null ,是写错了,所有的字段都是非空的。---------------------------------------------------
    我现在以几个能够保证唯一性的字段,进行连接取MD5作为主键,update速度update 2万条大概3分钟。PRIMARY KEY  (`smd5`),
    KEY `xxx` (`MerchId`,`TermId`,`TransDate`,`TransTime`,`AccNo`)每天先insert除Charge以外所有的字段大概4万条。然后update对应的Charge。
    现在我的程序执行的步骤是:
    1、先放弃主键smd5 .DROP PRIMARY KEY (因为经过测试发现在程序里逐条的获取MD5比较慢)
    2、insert所有字段(Charge默认0,smd5默认0),使用LOAD DATA LOCAL INFILE大概6万条4秒钟。
    3、然后,使用UPDATE tb_xf_all SET smd5 = MD5(CONCAT(,,,,))更新smd5。大概6万条2秒钟。
    4、然后,创建主键smd5 .ALTER TABLE tb_trans ADD PRIMARY KEY (smd5)
    5、然后,根据smd5调用存储过程去更新Charge的值。2万条更新大概3分钟。-------------------------------------------------------------------------
    不知道先放弃主键、再创建主键这样是不是合理,我测试了几次发现这样速度比较快。再次感谢各位前辈的指导,基础不扎实真痛苦,这次赶鸭子上架完成后,一定要好好学习基础。