Mybatis批量Insert及水平分表

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis批量Insert及水平分表相关的知识,希望对你有一定的参考价值。

首先是Mybatis批量insert

说一下核心部分,整个工程参考我的github,运行的main方法在org/xiongmaotailang/mybatis/batchinsert/DbUtil.java中,涉及到的脚本是sql.txt

需要的数据表示例,包括4个字段。

技术分享

CREATE TABLE `newspvuv` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `pv` bigint(11) DEFAULT NULL,
  `uv` bigint(11) DEFAULT NULL,
  `time` varchar(15) NOT NULL,
  PRIMARY KEY (`id`)
)

技术分享

接下来看看批处理的mapper.xml文件(工程中org\xiongmaotailang\mybatis\batchinsert\mappers\DataMapper.xml),批量插入方法的定义

技术分享

<mapper namespace="org.xiongmaotailang.mybatis.batchinsert.mappers.DataMapper">    
    <insert id="insertPVUV">
        insert into  ${table}(pv,uv,time) values(#{pv},#{uv},#{time})    </insert>
    <insert id="batchInsertPVUV" parameterType="java.util.List">  
        insert into  ${table}(pv,uv,time) values  
        <foreach collection="list" item="item" index="index"  
            separator=",">  
            (#{item.pv,jdbcType=INTEGER},#{item.uv,jdbcType=INTEGER},#{item.time,jdbcType=CHAR}  
            )  
        </foreach>  
    </insert>  </mapper>

技术分享

id="insertPVUV"是一条一条的写入的配置、id="batchInsertPVUV"是批量写入的配置。

对上边二个配置的main方法在DbUtil中。

技术分享

    public static void main(String[] args) throws InterruptedException {
        testInsert();
        testBatchInsert();
    }    private static void testInsert() {        long start=System.currentTimeMillis();        for (int i = 0; i < 1000; i++) {
            addPvUv(12,i,"123");
        }
        System.out.println("insert 1000 row :"+(System.currentTimeMillis()-start)+"ms");
    }    private static void testBatchInsert() {        long start=System.currentTimeMillis();
        List<NewsPvUv> list=new ArrayList<NewsPvUv>();        for (int i = 0; i < 1000; i++) {
            NewsPvUv n = new NewsPvUv(12, i, "123");
            list.add(n);
        }
        addPvUv(list);
        System.out.println("batch insert 1000 row :"+(System.currentTimeMillis()-start)+"ms");
    }

技术分享

上边对比了对1000条数据的二种写入方式,在我笔记本的测试结果如下图,可见批量写入的性能高效。

技术分享

 

水平分表

整个工程参考我的github

方法一:使用MD5哈希

技术分享

// 使用md5做hash水平分表
    public static String getTable(String mark, String prefix, int num) {        if (num == 0)            return prefix;
        String temp = md5(mark).substring(0, 2);        int hexdec = Integer.parseInt(temp, 16);// 16转成10进制
        int index = hexdec % num + 1;        return prefix + "_" + index;
    }    // 提供和php->md5一样的功能
    private static String md5(String txt) {        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(txt.getBytes("GBK")); // 问题主要出在这里,Java的字符串是unicode编码,不受源码文件的编码影响;而PHP的编码是和源码文件的编码一致,受源码编码影响。
            StringBuffer buf = new StringBuffer();            for (byte b : md.digest()) {
                buf.append(String.format("%02x", b & 0xff));
            }            return buf.toString();
        } catch (Exception e) {
            e.printStackTrace();            return null;
        }
    }

技术分享

方法二:使用移位

技术分享

// 使用移位分表
    /*
     * 如果我们预估我们系统的用户是100亿,单张表的最优数据量是100万,
     * 那么我们就需要将UID移动20来确保每个表是100万的数据,保留用户表(user_xxxx)四位来扩展1万张表     */
    public static String getTable1(int uid, String prefix) {        
        return prefix + "_" + String.format("%04d",(uid>>20));
    }

技术分享

源码来源:minglisoft.cn/technology

以上是关于Mybatis批量Insert及水平分表的主要内容,如果未能解决你的问题,请参考以下文章

Mybatis实现oracle批量插入及分页查询

mysql mycat 1.6.6.1-release 批量 insert 数据丢失问题(续)

玩转SpringBoot之整合Mybatis拦截器对数据库水平分表

springboot-mybatis 批量insert

怎样加快master数据库的写操作?分表原则!将表水平划分!

mybatis batch insert