记录一下线上数据cpu100%的问题

记录一下线上数据cpu100%的问题

  • 重现准备:
    1. 创建表:
      ps: 其中name + telephone字段创建索引
CREATE TABLE `t_test_index` (
  `id` int(20) DEFAULT NULL COMMENT '资源主键',
  `name` varchar(255) DEFAULT NULL,
  `address` varchar(255) DEFAULT NULL,
  `age` int(12) DEFAULT NULL,
  `telephone` varchar(50) DEFAULT NULL,
  KEY `name` (`name`),
  KEY `telephone` (`telephone`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
  1. 添加mock数据,mock100W条
 	@Test
    public void addData() {
        IntStream.rangeClosed(1, 1000000).forEach(i -> {
            TestIndex index = TestIndex.builder()
                    .id(i)
                	.name(RandomStringUtils.randomAlphanumeric(20))
                    .telephone( RandomStringUtils.randomNumeric(11))
                    .address( RandomStringUtils.randomAlphanumeric(40))
                    .age(Integer.valueOf(RandomStringUtils.randomNumeric(2)))
                    .build();
            indexMapper.insert(index);
        });
  1. 添加name telephone 部分重复的数据, 对主键 可以被4 整除的前10000条数据添加重复的name telephone,比如说我这里生成的name = asdjasdjjdajdads, telephone = 1318482579
 	@Test
    public void addData() {
        String name = RandomStringUtils.randomAlphanumeric(20);
        System.out.println("name = " + name);
        String telephone = RandomStringUtils.randomNumeric(11);
        System.out.println("telephone = " + telephone);
        for (int i = 4; i < 10000; i++) {
            if (i % 4 == 0) {
                TestIndex index = TestIndex.builder()
                        .id(i)
                        .name(name)
                        .telephone(telephone)
                        .build();
                indexMapper.updateById(index);
            }
        }
        System.out.println("end = ");
    }
  1. 执行sql查询:
explain select * from t_test_index 
where  telephone = '1318482579' and name = 'asdjasdjjdajdads'
  1. 我们查看执行计划结果:

执行计划结果
我们分析下:索引类型为index_merge, 用到了name + telephone索引
extra中显示为Using intersect(name,telephone); 意思是对name索引的结果集 + telephone索引的结果集(也就是id集合)进行交集,交集后到聚簇索引获取最好的结果集。
index_merge是mysql本身的优化,性能的影响并不是此type造成的,是因为索引构建不当造成的,我先说下我们的问题,我们的表数据是800W,其中is_deleted只包含’y’ ‘n’ 2个值,我们对其添加了普通索引,为n的数据行可能就存在几千条,后续和其他索引进行index_merge时,会非常耗时,因为要对接近800W的数据集进行交集造成数据库查询缓慢。如果并发量大,很容易造成cpu 100%的问题。

  • 结果描述:
    在对表进行添加索引时,切记不要对数据区分度不大的数据添加索引,这样多个索引进行检索时会添加不必要的行的比对,数据量大时 更容易出现索引问题造成检索更慢。

你可能感兴趣的:(java,mysql)