我是3y,一年CRUD经验用十年的markdown程序员‍常年被誉为优质八股文选手

今天想跟大家聊聊数据库层面上的事,austin项目继续更新(:今天聊的数据库都特指关系型数据库)

01、数据库选择

之前发了一张我可能要在austin项目上引入哪些技术栈的图,好多人问我分布式配置中心为什么不选择Nacos,而是用Apollo。却没人问我为什么数据库选择MySQL。

说起来MySQL,在网上看到的各类Java教程,几乎都是使用MySQL作为数据库。日常在群里聊各种数据库上的问题,也差不多都是MySQL,只有个别的可能用PostgreSQL和Oracle或其他

就连我在面试的时候,我也没被面试官问过:“你的数据库为什么选择MySQL啊?这块技术选型是怎么样的”

看到这里,是不是觉得我有答案了?其实我也没有。写到一半的时候发现我也说不出啥比较好的理由...既然我不知道,于是我就去看看人家是怎么说的。

https://www.zhihu.com/question/21793412/answer/32127410

总结原因可能是:

  • 前期MySQL免费开源易用,从众多厂商中硬生生搞出了生态。有了生态,很难就被干掉了。(最主要的
  • 互联网用MySQL就是用来存数据“低成本快速的数据存储插入方案”,要求也相对没那么高(这条我后面会详细聊聊
  • 很多时候对某技术选型并非是技术原因

而我,我只会MySQL。我在生产环境下只用过MySQL,当年我还是小白的时候接触过Oracle,但现在也基本忘得差不多了。

很多时候对某技术选型并非是技术原因(我是懒狗,我承认了)。近几年PostgreSQL很火,听说很多地方都比MySQL要好,感兴趣的小伙伴可以把austin项目的MySQL替换为PostgreSQL

对数据库选型感兴趣的大哥们也可以找点资料继续查阅资料,也很欢迎在评论区输出下自己的经验,这种话题讨论我觉得还是蛮有意思的。

跟着我一起做austin项目的小伙伴应该对关系型数据库都有所了解了,这里的基础我就不展开讲述了。对MySQL感兴趣或者准备要面试的同学,可以看看我《对线面试官》系列的MySQL章节(在各大博客平台中受到了不错的反馈)

02、ORM框架选择

记得几年前我刚接触数据库和Java的时候,那时候要用JDBC连接数据库来操作数据,我就很不解:明明我可以通过各种的数据库客户端就能对数据进行操作,为啥我要用JDBC,好麻烦啊!

至于为什么会有这种疑问,我也不理解我当时是怎么想的(哈哈哈哈)。后来想通了以后,也学习了很多在程序上“简化JDBC模板”的姿势(DBUtils/Hibernate/Spring JDBC/Mybatis/SpringData JPA)

我在生产环境中接触过的都是Mybatis,但这一次我在asutin项目中决定使用SpringData JPA作为ORM框架。

03、使用数据库的经验

这两年我是呆在互联网公司上班的,我就来聊下我个人所接触到的东西,分享下我的看法。

一般来说,每个业务团队维护着自己的数据库(一个业务团队可能就有好几个库),当我们需要某一个团队的相关数据时,团队会提供对应的RPC接口给公司内部业务使用。

这意味着数据逻辑对调用业务方而言,是透明的(调用业务方不需要关注其他团队数据库的任何信息,无论是数据库表设计还是具体的字段)。

这个好处是显然地:要某团队的业务数据,只要找到他们提供的接口就完事了。作为需求方,只需要调个接口就能拿到自己想要的数据。

回到数据库内部存储本身,我们会尽可能将表结构设计得更简单:在很多情况下,都会放弃数据库三大范式来设计表。

举个很简单又可能不太恰当的场景:一个作者可能会写多篇文章(意味着多篇文章会属于同一个作者) author:content(1:N)

那在初学的时候,可能有的教程会这样设计:author表content表autor_content_mapping表

但是,我们在实际中生产环境中很有可能是不设计这种关联表,而是直接把相关字段冗余在一张表里。这样在查询的时候,就能直接通过一张表查到对应的信息了,不用进行多层关联

如果按上面的结构进行查询:比如我要查到某一篇文章的作者基本信息,那我此时的动作是:

  1. 关联author_content表查到文章的authorId
  2. 通过authorIdauthor表查到作者的基本信息

如果我把authorId直接存到content表中,那就意味着少了去author_content表查询了。

:这里我不是说让你们把所有的信息都存在一张表里,一张表里有上百个字段,千万不要误会我的意思!

说起关联,又有一个能聊的话题:是否join(这个话题我曾经在我的交流群中聊过,不过也是各抒所见吧)。我在以前公司接触到的项目,在mapper.xml中都看不到join的身影,我写join只在hive写统计脚本的时候用到。

【强制】超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询时,保证被关联的字段需要有索引。

说明:即使双表 join 也要注意表索引、SQL 性能。

喜欢用join的会告诉你:我写join会让代码变得更简单。查数据太麻烦了,要查的数据会存到多张表里,直接在用join开发效率是最快的!

而我,我是支持在代码里写业务逻辑的。所有都是单表查询,在程序代码中对数据进行关联(数据库的JOIN能干到的事,在程序上一定能干得到)。这样的好处就在于:SQL简单,SQL易复用,SQL易优化

在绝大数情况下,我们的接口瓶颈都是来源于「数据库」,而非应用服务器。多JOIN且复杂的SQL是不好优化的,而简单的SQL是比较好优化的,并且我认为程序逻辑往往都要比SQL更容易维护

在我这两年在互联网公司中,关系型数据库在我的认知里,它就是作为一个支持事务的存储。如果我们存储的数据对事务没有要求的,可能压根就不需要存储至关系型数据库中。

现在数据源可选择的太多了,我们可以把数据存储到Redis(内存数据库)、Elasticsearch(搜索引擎)、HBase(分布式、可伸缩的大数据存储)、HDFS(分布式文件系统)、clickhouse(OLAP存储系统)等等等

基于上面这些背景下,我的查询SQL就不会复杂,那么Spring Data JPA不就很适合我了么?

04、开发之外的数据库

去到有一定规模的公司,都会有数据库相关的基础建设,下面提下常见的基础建设吧

、DDL和DML都需要走工单

生产环境的数据库理论都不能通过自己编写接口在程序中修改(高危动作),需要修数据或者建表都需要经过工单系统审核(一般是数据库负责人+DBA)

比如你提交建表申请,DBA会看你的表设计是否合理(是否有加索引等等)

、DQL查询线上数据需要权限

我们要查询线上的数据,一般都得申请库的权限,有了权限之后在公司内网特定的页面进行数据查询(我们一般只需要查团队内的数据,所以其实也还好,其他团队的数据库权限是不开放的,要数据一般只能通过接口获取)

、程序上一般不直连数据库(会有代理层)

一般只有线下数据库可以通过ip直连,线上数据库都会经过代理层(代理层可以做很多东西,包括监控鉴权分库分表等等)

、完备的监控告警

数据库作为一个很重要的存储之一(如果挂了是真的影响很大),会有完备的监控和告警。比如说执行SQL失败的告警、执行慢SQL的告警等等,对数据库的各种指标进行实时监控

05、austin建表DDL

如果有提前预习的同学,应该就知道在austin.sql下我放了两张表的DDL。为了让大家理解我在做什么,我来解释下这两张表的DDL具体是什么含义(为什么我要建这两张表)

message_template这张表开始解释吧,所有的字段我都添加了注释,应该还是比较容易看得懂的。

注:如果程序由于扩展导致数据库注释有落后,还是有必要更新下(造福后人)

我们需要让所有的消息都有一个「载体」,这个载体说白了就是模板,模板是austin系统的基石(有了模板,才能做业务处理,才能溯源,才能数据统计,才能扩展出一整套的建设...)

下面聊下几个可能大家有疑问的几个字段吧:

  • audit_statusflow_id:模板在发送之前需要经过审核(这在发送消息里非常重要,这会很大程度上能防止对消息的误发(相信大家也能看到各大公司都有过发错消息的报道)

  • msg_type消息类型:分隔不同的消息类型,可以在下发时让不同的类型走不同的通道进行实现消息隔离(营销类的消息即便堵住了,也不会影响到通知类的消息)

  • send_account发送账号:一个渠道内可能会有多个账号发送(比如,邮件渠道可以选择不同的邮件组进行发送、短信渠道可以选择不同的短信类型账号进行发送)

  • deduplication_timeis_ngiht_shield平台规则:作为发送类型的组件(平台),需要有通用的规则。而去重和夜间屏蔽下发这种就很适合在平台内做

  • msg_conteng:这个字段是作为消息内容发送的核心,不同的渠道对应下发的格式都不一样,我后面会直接将JSON存储进去。支持占位符的方式进行替换

  • ...

有可能后续还会扩展字段(毕竟在初期考虑设计表的时候,不会尽全尽美)。这种作为模板或者理解为配置的表,从使用上就注定它不会有很大的数据量。

下面来看下sms_record表吧,其实这表能说的不多(就是要把短信发送的记录以及短信的回执存储进去)。它的作用一方面是能追踪到为何发送给某个用户的短信失败了,另一方面是将这些记录进行关联做对账使用。

06、总结

这篇文章其实想我聊的是:数据库是一个很重要的角色,如果它挂了会影响很大很大。但同时,我们很多时候都是“轻量级”地去使用它(通过简单的SQL),它的存在很多时候是因它能很好地支持事务(数据强一致性)。

我们最能够信任的数据就是存储在数据库的,其他的存储我们可能担心会丢、会多、会不实时等等(这是数据库比其他存储的最大的优势)

我说得不对一定,不要以我的为准,我们可以在评论区聊

欢迎关注我的微信公众号【Java3y】来聊聊Java面试,对线面试官系列持续更新中!

【对线面试官+从零编写Java项目】 持续高强度更新中!求star!!原创不易!!求三连!!

Gitee链接:https://gitee.com/austin

GitHub链接:https://github.com/austin

最新文章

  1. 数据结构之C语言实现哈夫曼树
  2. Rafy 领域实体框架 - 树型实体功能(自关联表)
  3. Struts2 输入格式自动校验的一些注意事项
  4. 关于asp.net与jquery ajax 的一些补充
  5. GLSL Entry point not found
  6. 水题 Codeforces Round #300 A Cutting Banner
  7. winserver 2008 r2 iis7.5 实现php wordpress url静态化操作步骤(UrlRewrite实现)
  8. 当年的笔记_apache配置虚拟主机
  9. I - Navigation Nightmare-poj 1984
  10. Hibernate中HQL的日期差值计算,可计算相差多少秒
  11. Arduino 各种模块篇 粉尘传感器 dust sensor 空气质量检测
  12. mybatis笔记02
  13. 【转载】JVM系列一:JVM内存组成及分配
  14. 理解-const
  15. 【Alpha go】Day 2!
  16. kernel TCP time wait bucket table overflow
  17. Oracle sql的基本优化写法和思路。
  18. win7下hadoop编程eclipse的配置
  19. Tensorflow 运行警告提示 Your CPU supports instructions that this TensorFlow binary was not compiled to use
  20. 回顾爬虫的时候的一些小TIPS

热门文章

  1. [BUUCTF]PWN——[HarekazeCTF2019]baby_rop2
  2. USACO 2021 Contest 1 Bronze 题解
  3. Django 中间件理解
  4. 关于Marshal 类的整理
  5. docker部署验证码项目报错:at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264)
  6. MySQL查看数据库连接数
  7. Maven配置使用阿里云镜像
  8. 【LeetCode】448. Find All Numbers Disappeared in an Array 解题报告(Python)
  9. 【九度OJ】题目1179:阶乘 解题报告
  10. Class Activation Mapping (CAM)