上周末花了几个小时刷完《SQL反模式》这本书,书里介绍了数据库应用开发者最长遇到的一些问题,虽然这本书面向的读者是使用数据库的应用开发者,但它对数据库管理员、数据库开发者同样会有启发,强烈推荐阅读。本书涉及的问题包括但不限于
- 如何存储多值属性?
- 如何使用关系模型表达树结构?
- 如何建立主键规范?
- 如何支持可变的属性/字段?
- 如何从表中随机选择一行?
- 如何实现文本查询的需求?
- 如何存储文件类型数据?
- 如何限定列的有效值?
- 如何表达精准浮点数?
10.如何写出安全(难以 SQL 注入)的 SQL 语句? - ...
针对上面的问题在实际的开发场景中都经常遇到,作者介绍了一系列「反模式」的设计思路,我发现很多都是开发过程中很容易犯的错误。以「如何存储多值属性」为例,最直观的反模式设计思路就是「复用原来字段,格式化的逗号分割列表」,如果需求比较局限,联系人数量不会无限制扩展,针对联系人字段也不会经常有查询、聚合需求,这种方法的确成本很低。
但实际上这种方法缺点很多,比如(1)针对这个字段的查询,基本都得使用正则表达式,而正则表达式没有确定的规范,不同的数据库支持都不一样,导致写出的 SQL 也不具备通用性。(2) 针对该字段里属性的查询无法使用索引 (3)列长度有限制,属性数量扩展有上限 ... 而这些随着应用需求的不断变化,可能对系统产生非常大的影响,扩展起来非常麻烦。
从数据库开发者的角度看,对于这么多可能误用的场景,我们需要思考数据库服务本身能做什么工作来简化、或者规避问题,比如
- 很多新的存储引擎都具备了 SAMPLE 随机取样的能力,方便用户随机获取记录,避免了用户
- 阿里云数据库上,专门有针对防 SQL 防注入的检查,减小了用户犯错造成的影响
- 对于属性可扩展的需求,SQL 可能并不是最佳需求,一些基于 KV、Document 的接口的数据库,如 Redis、MongoDB,可能是更加的选择。
- 对于文件存储的需求,存储在数据库节点同机器上文件系统上有很多问题, 但量大的时候,存储在数据库里也无法满足需求;目前比较常用的方案时,文件存储到专门的分布式文件系统里,数据库里存储对象的标识名。