• mysql数据表分表策略2(转)


    mysql分表方法:

    方法一、 做数据库集群! 主从数据库 双向热备份(或一对多的数据库实时备份策略),这样可将数据库查询分摊到几个服务器去(可跟服务器负载均衡结合起来架构)

    优点:扩展性好,没有多个分表后的复杂操作(php代码)
    缺点:单个表的数据量还是没有变,一次操作所花的时间还是那么多,硬件开销大。

    方法二、 根据特殊情况,按照特定规则分表:比如 用户聊天表,
    message_00,message_01,message_02……….message_98,message_99.然后根据用户的ID来判断 这个用户的聊天信息放到哪张表里面,你可以用hash的方式来获得,可以用求余的方式来获得,方法很多,比如用hash的方法来获得表名:

    function get_hash_table( $table , $userid ) {
         $str = crc32( $userid );
         if ( $str <0){
             $hash = '0' . substr ( abs ( $str ), 0, 1);
         } else {
             $hash = substr ( $str , 0, 2);
         }
         return $table . '_' . $hash ;
    }
    echo get_hash_table( 'message' , 'user18991' );     //结果为message_10
    echo get_hash_table( 'message' , 'user34523' );    //结果为message_13
    

      


    优点:避免一张表出现几百万条数据,缩短了一条sql的执行时间
    说明一下,上面的这个方法,告诉我们user18991这个用户的消息都记录在message_10这张表里,user34523这个用户的消息都记录在message_13这张表里,读取的时候,只要从各自的表中读取就行了

    缺点:当一种规则确定时,打破这条规则会很麻烦,上面的例子中我用的hash算法是crc32,如果我现在不想用这个算法了,改用md5后,会使同一个用户的消息被存储到不同的表中,这样数据乱套了。扩展性很差。

    方法三:利用merge存储引擎来实现分表

    假如有一张用户表user,有50W条数据,现在要拆成二张表user1和user2,每张表25W条数据,

    CREATE TABLE `test`.`user` (
    `id` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
    `username` VARCHAR( 300 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
    `pwd` VARCHAR( 200 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
    `email` VARCHAR( 300 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL
    ) ENGINE = MYISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
     
    CREATE TABLE `test`.`user1` (
    `id` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
    `username` VARCHAR( 300 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
    `pwd` VARCHAR( 200 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
    `email` VARCHAR( 300 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL
    ) ENGINE = MYISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
     
     
    CREATE TABLE `test`.`user2` (
    `id` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
    `username` VARCHAR( 300 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
    `pwd` VARCHAR( 200 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
    `email` VARCHAR( 300 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL
    ) ENGINE = MYISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
     
     
    INSERT INTO `test`.`user` (`id`, `username`, `pwd`, `email`) VALUES (NULL, 'user1' , '123' ,'user1@adsf.com' );
    INSERT INTO `test`.`user` (`id`, `username`, `pwd`, `email`) VALUES (NULL, 'user2' , '123' ,'user2@adsf.com' );
    INSERT INTO `test`.`user` (`id`, `username`, `pwd`, `email`) VALUES (NULL, 'user3' , '123' ,'user3@adsf.com' );
    INSERT INTO `test`.`user` (`id`, `username`, `pwd`, `email`) VALUES (NULL, 'user4' , '123' ,'user4@adsf.com' );
     
    INSERT INTO user1(user1.id,user1.username,user1.pwd,user1.email) SELECT user.id,user.username,user.pwd,user.email FROM user where user.id >=2;
    INSERT INTO user2(user2.id,user2.username,user2.pwd,user2.email) SELECT user.id,user.username,user.pwd,user.email FROM user where user.id >2;
     
    DROP TABLE `user`;
    CREATE TABLE `test`.`user` (
    `id` INT( 11 ) NOT NULL ,
    `username` VARCHAR( 300 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
    `pwd` VARCHAR( 200 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
    `email` VARCHAR( 300 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
    INDEX ( `id` )
    ) ENGINE = MRG_MYISAM UNION=(user1,user2) INSERT_METHOD=LAST CHARSET=utf8  AUTO_INCREMENT=1 ;
     
    测试:
    INSERT INTO `user` (`id`,`username`, `pwd`,`email`) VALUES(5, 'user5' , '123' , 'user5@adsf.com' );
    INSERT INTO `user` (`id`,`username`, `pwd`,`email`) VALUES(6, 'user6' , '123' , 'user6@adsf.com' );
    INSERT INTO `user` (`id`,`username`, `pwd`,`email`) VALUES(7, 'user7' , '123' , 'user7@adsf.com' );
     
     
    INSERT INTO `user` (`username`, `pwd`,`email`) VALUES( 'user8' , '123' , 'user8@adsf.com' ); 
    //这样的话 id居然是0  这个有点奇怪,如果解决不了,每次插入新数据,要加上last_id。。。。(php代码得改)

    优点:扩展性好,并且php代码几乎不用改但如此分表要注意点东西:
    1.不能将merge存储引擎变成其它存储引擎
    2.执行一个 insert,数据进入第一个或者最后一个 myisam 表(取决于 insert_method 选项的值)。mysql确保唯一键值在那个 myisam 表里保持唯一,但不是跨集合里所有的表。
    3. merge表 必须和分表的结构一模一样····

    缺点:这种方法的效果比第二种要差一点

    建议:具体情况具体分析,方法一、方法二、方法三综合使用。

  • 相关阅读:
    django 之 ContentType的使用
    redis的使用与 django的redis的使用
    django之缓存的用法, 文件形式与 redis的基本使用
    python全栈脱产第20天------常用模块---re模块和subprocess模块
    python全栈脱产第19天------常用模块---shelve模块、xml模块、configparser模块、hashlib模块
    python全栈脱产第4天------if判断、while和for循环、数据类型(int和float)
    python全栈脱产第18天------包的使用和logging模块
    python全栈脱产第5天------字符串(str)类型和列表(list)类型
    python全栈脱产第17天------常用模块---time模块、datetime模块、shutil模块、random模块、sys模块、os模块、pickle模块、json模块
    python全栈脱产第16天------模块循环导入问题、区分python文件类型的途径、文件的搜索路径、软件开发的目录规范
  • 原文地址:https://www.cnblogs.com/sandea/p/5472058.html
Copyright © 2020-2023  润新知