前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2021-01-06:mysql中,我存十亿个手机号码...

2021-01-06:mysql中,我存十亿个手机号码...

原创
作者头像
福大大架构师每日一题
修改2021-01-07 10:11:35
8940
修改2021-01-07 10:11:35
举报

福哥答案2021-01-06:

答案来自此链接:

首先提出假设:

考虑一下这几个问题:

手机号码都是数字吗?

都是中国的手机号码吗?

会按照手机号等值查询吗?

会按照手机号范围查询吗?

需要手机号列唯一约束吗?

最简单情况(中国手机号,11位数字)就用数值类型bigint存储即可,建索引。

考虑三种类型,BigInt,Char,Varchar

这几种类型在 InnoDB 引擎下默认行格式的存储方式为:

1.对于 bigint 类型,如果不为 NULL,则占用8字节,首位为符号位,剩余位存储数字,数字范围是 -2^63 ~ 2^63 - 1 = -9223372036854775808 ~ 9223372036854775807。如果为 NULL,则不占用任何存储空间。

2.对于定长字段,不需要存长度信息直接存储数据即可,如果不足设定的长度则补充。对于 char 类型,补充 0x20, 对应的就是空格。

3.数据开头有可变长度字段长度列表,所以 varchar 只需要保存实际的数据即可,不需要填充额外的数据。正是由于这个特性,对于可变长度字段的更新,一般都是将老记录标记为删除,在记录末尾添加新的一条记录填充更新后的记录。这样提高了更新速度,但是增加了存储碎片。

由于手机号不更新,并且不同国家的手机号长度不同,并且可能有特殊字符,字符类型在默认的编码和排序规则下进行范围匹配也能满足我们的需求,所以为了节省空间,使用 varchar 类型。

分区

这个数据量比较大了,需要用分区。phone 可以作为分区键,可以按照范围分区,也可以按照 hash 分区。

这样查询某个手机号是否存在这种业务就能更快,因为一张表被划分成了很多张小表。并且如果涉及多张小表 MySQL 还可以多线程并发查,效率提升很多。如果考虑获取某一号码段的所有手机号,那最好还是按照范围分区,可以使逻辑查询范围更小。但是 hash 分区数据可能比范围分区更加均衡。

注意,对于 HASH 分区个数最好是 2^n。因为对于 2^n 取余相当于对 2^n - 1 取与运算,增加了查询时的计算分区的效率.

进一步优化

对于查询某个手机号是否存在,可以在数据库上层加一层布隆过滤器,提高效率。

同时为了提高准确性,可以通过号码号段,不同号段使用不同的布隆过滤器。在插入数据库的同时,放入布隆过滤器中。如果布隆过滤器中检测不存在,则肯定不存在。为了减少布隆过滤器的误判概率,可以使用更多的布隆过滤器,同时设置交叉范围,例如一个 13000000000~13200000000 用布隆过滤器 A,13100000000~13300000000 用布隆过滤器 B, 13211111111就要经过布隆过滤器 A 和 布隆过滤器 B 的验证。


评论

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档