目录
1、问题的背景
我们系统是一个互联网系统,注册用户非常多,有上百万数据,现在需要统一每个user_id注册来源的url地址,表结果如下:
CREATE TABLE `sys_reg_url_stat_v1` (
`id` int(8) NOT NULL COMMENT '主键',
`url` varchar(255) DEFAULT NULL COMMENT 'url',
`reg_time` datetime DEFAULT NULL COMMENT '注册时间',
`user_id` int(8) DEFAULT NULL COMMENT '用户Id',
PRIMARY KEY (`id`),
KEY `url` (`url`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='对注册来源url进行统计';
请注意,url上有一个普通索引,因为经常需要根据url查询,分组统计,所以对该索引创建了一个普通BTree索引,现在分析以下sql语句
select * from sys_reg_url_stat_v1 where url='https://www.cnblogs.com/nineyang/p/Arif';
因为url是一个长字符串长度值通过为100个字符左右,并且url的前缘重复率为80%以上,所以不能对url前缀创建前缀索引,而如果针对整个url字符串的值创建索引,导致索引数据的前缀大量重复,索引效率不高。
2、实施方案
为了解决上述问题,我们增加一个新字段,url_crc32来存储url的哈希值,利用crc322哈希函数生成哈希值 ,然后在url_crc32上创建普通索引,这样索引值的选择性大大地提高,基本不重复,
哈希冲突也非常低,利用冗余提高查询查询性能。
3、效果对比
3.1 优化之前
3.2 优化之后
CREATE TABLE `sys_reg_url_stat_v2` (
`id` int(8) NOT NULL COMMENT '主键',
`url` varchar(255) DEFAULT NULL COMMENT 'url',
`last_access_time` datetime DEFAULT NULL COMMENT '上次访问时间',
`url_crc32` varchar(32) DEFAULT NULL COMMENT 'url的crc32值',
`reg_time` datetime DEFAULT NULL COMMENT '注册时间',
`user_id` int(8) DEFAULT NULL COMMENT '用户Id',
PRIMARY KEY (`id`),
KEY `url_crc32` (`url_crc32`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='对注册来源url进行统计';
可以明显的观察到key_len大大降低,fkiltered也降低了,我这里的样本数据只有200条,如果该表数据有100百万,则性能优化是相当可观的。