NoSQL和MemeryCache的出现意味着传统数据库使用方式的变革吗?

摘要:
您可以看到,Redis和MemeryCached现在存储名称-值对,没有逻辑。算了吧。更让我困惑的是,将NoSQL的概念应用于关系数据库是否合适?关于数据库系统的选择,我不反对NoSQL或MemeryCached的概念。毕竟,它们被用来处理不同的情况。由于数据量大、访问量大、数据结构相对简单,以及用户访问的及时性和区域性,这种NoSQL+MemeryCache方案是合理的,甚至是唯一的选择。我认为在员工平台或项目管理系统上使用MemoryCache是非常不可靠的。
故事的起源

作为软件工程专业出身的程序员,之前所接受的关于数据库的教育都是基于关系型数据库。对key-value based数据库和document-based数据库的都只是仅仅了解而已。

最近公司要做一个类似电商的系统,我来负责数据库的设计和接口的提供。当然,我们使用的数据库也是传统的关系型数据库SQL SERVER 2005,所以我也并没有什么太大压力。

但是当头儿看到我设计的分类系统的数据库表结果时意见很大,一翻沟通下来,我基本上就崩溃了。他的一翻话基本上推翻了我对数据库的基本认识。


我的设计

要实现的分类是书籍分类体系,会至少有4层,总共大约有几百个分类。我很自然地想到了邻接表(Adjacency List)模式。然后设计了的表结构大体如下:

列名CategoryIdParentIdName
描述主键父键分类名

当然还有别的字段,与问题无关就不列了。

使用CTE递归的方式来获取一个分类下的子分类树。我考虑数据量并不大,所以性能上应该不成什么问题。

和头儿的争论

头儿看到我的设计,直接说,不用这么麻烦了,不是有4层吗?那就用4列,一列表示一级。

我说国图法分类可能有7层以上。他说那就7列好了。

我说这样数据量会有大量冗余,更新起来会很麻烦。

头儿说,我之前做过很多树型结构,一开始也和你一样。但是做着做着就发现查询继承关系好麻烦啊,还不如直接用列存储下来。

我说查询继承的代码我已经写好了,用CTE递归我并不觉得麻烦啊。

头儿说,不要用递归,我们要为读优化,而不是为写优化。

这个我完全赞同,但是这个数据量并不大,但是我还是觉得这个做法很山寨。不符合数据库的基本范式啊。

他说你知道范式,也要了解反范式。而且这个数据库本身不要包含业务逻辑。你看现在出来的Redis和MemeryCached,存的都是名值对儿,没有逻辑。逻辑是给业务处理的。什么是程序?程序就是算法加数据,数据和逻辑是要分开的。

我说从属关系也是逻辑吗?数据一致性也是逻辑吗?

应该算啊,数据库就是负责存储数据的就够了,你自己好好想想吧。

之后我还是坚持了自己的做法,头儿勉强接受,但是要多加一个Path列,存储这个分类的所有父节点。

这个我倒是同意加上,这属于为特定查询做的优化。

背景和现状

我进这个项目的时候,这个项目的数据库基本上已经建立完了。现在只是由于业务扩展需要新建数据库表。刚进公司的时候,我就觉得这里的数据库用法很诡异。

  1. 只有主键,没有外键,也就是数据库基本无从保证数据的一致性。
  2. 没有使用ORM,需要在C#代码中拼SQL来实现业务对象的读取和写入。
  3. 不允许使用存储过程。这会引入过多的业务逻辑。
  4. 我也没见过任何View,任何Trigger,任何自定义函数。

现在发现这些现状与头儿的想法其实是比较一致的。但是给人的感觉就是把SQL SERVER当作一个Key-Value的Database来实用。自然也就不需要那些SQL SERVER的功能。

但是我很奇怪,这样的用法,为什么不直接用No SQL方案呢?不用也就算了,更让我困惑的地方就在于,把No SQL的理念用在关系型数据库上合适吗?

我在这里也没有看到过任何数据库性能Profiling的代码,对于数据库性能的考量,基本上依赖数据库服务器的CPU占用。(也许有测试人员做过我不知道而已吧。希望是这样。)我们仅有的一名DBA也于年前离职了。

我的想法

我一直觉得数据库设计是一项很重要很复杂的工作,需要了解业务需求,需要了解用户的使用方式,需要能够遇见到基本的可变性,需要对数据库底层机制有深入的了解,等等等等。也听过很多数据库高手改写一段SQL,就让数据库查询变得飞快的故事。而且一切优化都应该有实际的数据来说话。也许我们头儿在数据库设计上有相当的功力,很有感觉。但是真的是这样的吗?我有我自己的想法,不知道是不是正确,但希望能和大家讨论一下。

关于反范式和优化

反范式作为一种数据库优化方案,我并觉得和其它的优化有什么根本上的不同。但是从优化的次序上来讲,我个人觉得应该先在查询的SQL上做足功夫,不行了再祭出反范式这个以空间换时间的杀手锏。不应该是从数据库设计一开始就惦记着的事情,尤其是这还是在关系型数据库上。当然,资深人员一眼就能感觉出哪里需要这么干当然更好。不过对于上面的情况,我个人觉得不需要。

关于数据库不能有逻辑

这句话首先需要澄清什么属于逻辑。由于这是我们头的观点,我也没有跟他详细讨论过这个问题。我来讲下我的理解吧。数据库在设计之初就是为某个业务设计的,脱离了这个业务,这个设计本身也没有了意义。所以我不认为逻辑从数据库分离能让数据库可以被重用。但是数据库包含了过多的逻辑会增加数据库服务器的负担,所以逻辑还是少放在数据库为好。所以我基本同意这句话。

但是,我认为。数据关系(如外键)不属于逻辑,数据完全性不属于逻辑。而且这些就应该主是由数据库来保证的。Web 服务器可以去检查外键,检查唯一约束,但是即使Web服务器不做这些,数据库也应该做到这些。

最常见的就是数据插入和更新,如果涉及到多张表,那这些SQL写入一个存储过程以方便外界调用是很好的。同时,存储过程或是View也可以把数据库表设计与程序之间的依赖解除,在一些简单的情况下实现不修改程序而对数据库表结构进行变更。使用存储过程也许会给数据迁移带来麻烦,但是有谁没事儿换数据库呢?

我们目前这种在程序中拼SQL去操作数据库的做法,我没有看到什么优势。纯粹就是为了“数据库不能有‘逻辑’”而拆分出来的东西。

关于数据库系统的选用

我并没有反对NoSQL或MemeryCached的理念,毕竟是用于处理不同的情况问题的。

像微博、社交、互动相关的系统。因为数据量大,访问量大,数据结构相对简单,用户访问具有时效性、地域性,使用这种NoSQL+MemeryCache方案是合理甚至是唯一的选择。但是任何产品或是理念都有它适用的范围,没有银弹。把 MemoryCache用在员工作业平台或是项目管理系统上我觉得就相当的不靠谱。

但是电商系统似乎是处于两者之间的一种模式,而且我们的业务量在可预见的未来也不会增长到淘宝的那个级别。我和头的争论也就源于这些理念上的差别,他像是在建立大统一理论,把各种先进思想整合在一起,而我又不确定这是创新呢?还是不伦不类的方式?于是有了题目上的疑问。而按头的说法,也许这就是思考问题层次上的差别。

我在数据库设计上并没有什么经验,却又做不到别人说什么我就听什么。上面只是我根据对于数据库自身的理解产生的一些想法,还很不成熟,希望大家能说说自己的见解。如果实在看不下去了,也欢迎吐槽。

免责声明:文章转载自《NoSQL和MemeryCache的出现意味着传统数据库使用方式的变革吗?》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇在Git中如何撤销上一次的commit【Qt开发】Linux下Qt开发环境的安装与集成下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

如何在oracle中导入dmp数据库文件

如何在oracle中导入dmp数据库文件 --如何在oracle中导入dmp数据库文件                          Oracle数据导入导出imp/exp就相当于oracle数据还原与备份。exp命令可以把数据从远程数据库服务器导出到本地的dmp文件,imp命令可以把dmp文件从本地导入到远处的数据库服务器中。 利用这个功能可以构...

SQL Server与Access数据库sql语法的差异

ACCESS结构简单容易处理,而且也能满足多数的应用程序要求,也是初学者的试牛刀。 随着时间的推移,大多数数据库应用程序都会发展,变得更复杂,并且需要支持更多用户。在 Access 数据库应用程序的生命周期的某个时刻,可以考虑升迁到 SQL Server,以优化数据库和应用程序的性能、可伸缩性、可用性、安全性、可靠性和可恢复性。升迁SQL Server的好...

NACOS集群搭建遇到的问题

搭建NACOS官网教程: https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html 这里说的很详细了。也有中文的。我就记录一下在搭建集群的时候遇到的问题 详情见:自己的有道云笔记,一下只是借鉴的问题处理方式 1.数据库连接问题:     nacos默认的数据库驱动是5.1.? 如果你的mysql版本...

python(八):python使用lmdb数据库

一、入门代码 LMDB的全称是Lightning Memory-Mapped Database(快如闪电的内存映射数据库),它的文件结构简单,包含一个数据文件和一个锁文件: LMDB文件可以同时由多个进程打开,具有极高的数据存取速度,访问简单,不需要运行单独的数据库管理进程,只要在访问数据的代码里引用LMDB库,访问时给文件路径即可。 让系统访问大量小文...

JAVA连接数据库

运行如下Java程序,学会JAVA连接数据库的方法。。 import java.sql.*; public class Test { public static void main(String[] srg) { String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; //加载...

pg数据库的备份和恢复

1 备份恢复方法 sql转储 文件系统级备份 连续归档 2 sql转储 sql转储方法的思想就是创建一个由SQL命令组成的文件,当把这个文件返回数据库时候,数据库利用其中的sql命令重建与转储状态一样的数据库实例。postgresql提供的工具是pg_dump,这个工具的基本用法如下: 备份:pg_dump dbname > outfile 恢复...