用UUID做主键和用19位的bigint做主键,插入性能那个更ok?

解惑:
在公司的机器上跑了30万的数据,建了一个test_sg_student(主键为UUID)和 test_bigintAsString_t (主键为19位的bigint),分别用10个线程和批处理进行插入,发现性能相差接近100倍,很明显是UUID做主键的表插入时间是最慢的,根据底层索引B+树来思考,其实答案也油然生成,UUID的无序和空间占的大小导致插入时候要耗费更多的时间去创建和维护索引


test_bigintAsString_t表
 test_bigintAsString_t


test_sg_student表
这里写图片描述


用prepareStatement的batch处理,语句经过预编译,将每1000个记录为一个batch提交,计算时间性能相差100多倍

test_bigintAsString_t表的插入:
这里写图片描述
test_sg_student表的插入:
这里写图片描述

在mysql进行一次全部数据的扫描,也发现uuid做主键的表性能极差,一次查询竟然达到了12秒之巨,哪怕是为UUID建立前缀索引,也仅仅是快了1秒左右,而对插入更是没什么用处

这里写图片描述


下面是进行检测插入的java代码,使用的是druid连接池


import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/*
    这是对UUID做主键的表进行插入时间消耗检测,只是为了检测,代码不足之处可以提出来~
*/
public class test {
    public DruidManager druidManager = DruidManager.getInstance();
    public  void test() {
        Connection con = null;
        PreparedStatement ps = null;
        AtomicInteger errori =  new AtomicInteger(0);
        AtomicInteger successi =  new AtomicInteger(0);
        String sqllanguages = "insert into test_sg_student(id,name,age,loves,cardnum) values(?,?,?,?,?)";

        //ResultSet rs = null;
        try {
            con = druidManager.getConnection();
            con.setAutoCommit(false);
            ps = con.prepareStatement(sqllanguages);
            while(i.get() < 10) {
                for (int id = 0; id < 1000; id++) {
                    ps.setString(1, UUIDUtil.generateOriginalUUID());
                    ps.setString(2, "student" + id);
                    ps.setInt(3, 20);
                    ps.setString(4, "test");
                    ps.setString(5, "cardum");
                    ps.addBatch();
                }
                long starttime = System.currentTimeMillis();
                ps.executeBatch();
                con.commit();
                long endtime = System.currentTimeMillis();
                System.out.println("========================================");
                System.out.println(Thread.currentThread().getName()+"add 1000个记录第"+successi .incrementAndGet()+"次");
                System.out.println("此次花费时间:" + (endtime-starttime)/1000 + "秒!!");
                System.out.println("---------------------------------------");
            }
        }catch (Exception e){
            e.printStackTrace();
            System.out.println("failed"+errori.incrementAndGet());
        }finally {
            try{
                ps.close();
                con.close();
            }catch (Exception e){
                 e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"线程完成");
        }
    }


    public static void main(String[] args) throws Exception{
        long starttime = System.currentTimeMillis();
        test t = new test();
        ExecutorService exes = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        for (int threadNum = 0 ;threadNum<10;threadNum++){
            exes.submit(new Runnable() {
                @Override
                public void run() {
                        t.test();
                }
            });
        }

        exes.shutdown();
        exes.awaitTermination(1, TimeUnit.HOURS);
       //t.test();//单线程跑和多线程跑表现的性能比较接近
        long endtime = System.currentTimeMillis();
        System.out.println("程序花费时间:" + (endtime-starttime)/1000 + "秒!!");
    }


}

程序的单线程表现结果在上面几张图

结论:尽量使用自增的,占内存小的字段作为主键

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值