mysql or mongodb

290 阅读7分钟

数据库分为关系型数据库和非关系型数据库

常用的关系型数据库有mysql、oracle、sql server

常用的非关系型数据库有mongodb、redis

什么是mysql?

了解mysql,首先要知道关系型数据库。

关系型数据库是信息的集合,它以预定义的关系组织数据,数据存储在一个或多个由列和行构成的表(或“关系”)中,用户可以轻松查看和理解不同数据结构之间的关系。关系是不同表之间的逻辑连接,根据这些表之间的交互建立。

这样笼统的定义大家可能不清楚,我们细分为几个点来讲解:

  • 基本组成: 数据库、表、行、列
  • 预定义结构:高度依赖二维表格,每个表格里的字段都是预先定义好的,以客户表为例,需要预先定义好字段类型idnamephoneaddress

    • +----+---------+-------------+-----------+
      | id | name    | phone       | address   |
      +----+---------+-------------+-----------+
      |  1 | 客户1   | 13127354603 | 深圳市    |
      |  2 | 客户2   | 12346253843 | 广州市    |
      |  3 | 客户3   | 13123423424 | 佛山市    |
      +----+---------+-------------+-----------+
      
  • 表与表之间有联结关系:以客户表和订单表为例,客户表跟订单表是通过foreign key: client_id关联起来的

    • +------+-----------+-----------+---------------+--------+
      | id   | client_id | goods     | issuance_date | status |
      +------+-----------+-----------+---------------+--------+
      | 1001 |         1 | 电脑      | 2022-10-12    |      1 |
      | 1002 |         2 | 笔记本    | 2022-10-20    |      2 |
      | 1003 |         3 | 手机      | 2022-11-11    |      2 |
      +------+-----------+-----------+---------------+--------+
      
  • SQL 语句:通用的sql语言,对数据表的建立和操作都依赖sql语句
CREATE TABLE IF NOT EXISTS orders(
        id int UNSIGNED PRIMARY KEY AUTO_INCREMENT,
        client_id int UNSIGNED NOT NULL COMMENT '关联客户id',
         goods varchar(100) NOT NULL COMMENT '货物',
        issuance_date Date NOT NULL COMMENT '发货日期',
        status int UNSIGNED NOT NULL COMMENT '订单状态',
        FOREIGN KEY (client_id) REFERENCES client (id)
) ENGINE = InnoDB CHARSET = utf8;

insert into orders (client_id, goods, issuance_date, status) values (3, '手机', '2022-11-11', 2);

什么是mongodb?

mongodb是非关系型数据库,也叫NoSql数据库。主要指那些非关系型的、分布式的,且一般不保证ACID的数据存储系统。NoSQL提出了另一种理念,以键值来存储,且结构不稳定,每一个元组都可以有不一样的字段,这种就不会局限于固定的结构,可以减少一些时间和空间的开销。使用这种方式,为了获取用户的不同信息,不需要像关系型数据库中,需要进行多表查询。仅仅需要根据key来取出对应的value值即可。

  • 基本组成:数据库、集合、文档、域
  • 动态结构:在sql中,必须定义好地段和表结构之后,才能够添加数据,例如定义表的主键、索引、外键等。在Nosql数据库中,数据可以在任何时候任何地方添加。不需要预先定义,也不需要预先创建表格,字段也不需要保持一致。
{
        "_id" : ObjectId("6356459b0ad81bc66bfd4b6c"),
        "client_id" : "1",
        "goods" : "电脑",
        "issuance_date" : "2022-10-12",
        "status" : 1
}
{
        "_id" : ObjectId("635751d00ad81bc66bfd4b6e"),
        "client_id" : "1",
        "goods" : "电脑",
        "issuance_date" : "2022-10-12",
        "update_date" : "2022-12-12"
}
  • NoSql: Not Only Sql,不像传统的Sql语言,采用结构化的查询语句
db.orders.insert({
    client_id: '1',
    goods: '电脑', 
    issuance_date: '2022-10-12', 
    status: 1
})

能力对比

对比mysqlmongodb
数据结构预定义对象数组json
动态schema不支持,可以把字段类型设置为JSON来代替支持
INSERT INTO orders( client_id, goods, issuance_date, status) VALUES( 3, '货物', '2022-12-12', 3);db.orders.insert({ client_id: '1', goods: '电脑', })
drop table orders;db.collection.drop()
update orders set goods='苹果' where id = 1004;db.orders.update({goods: "电脑"},{ $set:{title: "手机"} })
select * from orders;db.orders.find().pretty()
语句语法为传统的sql语法,对于新人上手有一定的心智负担。可以通过封装第三方库比如sequelizetypeorm来支持,但是orm库本身也有自己的api语法,而且对于联表查询或者复杂语句,支持起来也需要熟练相关api,这对于新人入手无疑也是有一定的心智负担的。语法更加接近面向对象编程,对于没接触过传统数据库语法的,易于上手,没有心智负担
可视化工具MySQL Workbench、Sequel Pro、HeidiSQL、NavicatRockmongo、Navicat for MongoDB、NoSQLBooster for MongoDB
引擎常用的有InnoDB、MyISAM、MEMORY常用的有mmapv1、inMemory、WiredTiger
事务事务是一种处理机制,用来管理数据语句必须成批的执行,以保证数据库不会包含不完整的执行结果。通俗点说,事务包含的数据语句要么完整执行,要么不执行。如果执行不完整或者发生错误,则进行回退。事务的特性:原子性、一致性、隔离型、持久性。事务的常见操作:事务(transaction)、回退(rollback)、提交(commit)、保留点(savepoint)
事务支持只有InnoDB引擎支持BEGIN; DELETE FROM client WHERE id = 1; DELETE FROM orders WHERE client_id = 1; COMMIT;3.6版本开始支持const session = db.getMongo().startSession(); session.startTransaction({readConcern: { level: 'majority' },writeConcern: { w: 'majority' }}); const client = session.getDatabase('test').getCollection('client'); const orders = session.getDatabase('test').getCollection('orders'); client.remove({'id': 1}); orders.remove({'client_id': 1}); session.commitTransaction();
复杂查询支持INNER JOIN(内连接,或等值连接)、LEFT JOIN(左连接)、RIGHT JOIN(右连接)、GROUP BY、SUM、AVG等通过聚合操作aggregate可以使用lookuplookup、group、sumsum、avg等
概念:锁是计算机用以协调多个进程间并发访问同一共享资源的一种机制。要解决的是并发请求下资源分配的问题,对于数据库来说,就是并发的读写。类型:读的共享锁(S)和用于写的排它锁(X),也叫悲观并发控制。读的意向共享锁(IS)和用于写的排它锁(X),也叫乐观并发控制。粒度:由大到小划分为全局锁、库锁、表锁、行锁、页锁、文档锁,粒度越小,越不易阻塞。比如数据库只支持表锁,将导致在锁情况下,其它资源无法对该表进入操作。如果可以支持行锁,那么其他资源对该表还是可以操作的,只是无法操作改行。死锁:死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。比如有个A、B两个请求都是对表C、D进行写入操作,A请求先对C加锁,还未对D进行加锁,而此时B请求却优先对D进行加锁,这样就导致A请求无法操作D,B请求无法操作C,进入了死循环。
锁支持默认支持表锁。InnoDB支持行锁。MyISAM额外支持页锁。2.2之前只有全局锁。2.2之后开始有库锁和表锁。3.0之后WiredTiger支持文档锁。
自动分片分片是一种将大型数据集分布在不同数据集合中的方法。在这里,用户可以选择一个分片键(具有单个或多个副本的主键)来确定集合中的数据分布,并将数据拆分为跨分片的不同范围。每个分片都充当单独的数据库,使用其他分片形成一个数据库有助于负载平衡并执行复杂的查询
自动分片支持可以通过分片框架MySQL Fabric实现天然支持通过分片进行水平扩展
性能从理论上讲,同等条件下,MongoDB 接收任何数据都比 MySQL 快,而且能接收的数据量也比 MySQL 多。因为Mongo使用的内存映射技术,用空间换取时间, 写入数据时候只要在内存里完成就可以返回给应用程序,这样并发量自然就很高,而保存到硬件的操作则在后台异步完成。但如果涉及到联表查询、分组等复杂语句以及大量用户访问时,对内存的要求也高,加上锁的影响,虽然mongodb也能支持,但这时候的访问效率可能反倒会不如mysql。不过,性能问题总归要看场景而言,不能一概而论。
应用场景- 如果你的业务对于存储要求很高、存储量大、并且业务结构有很大的不确定性,那么mongodb是一个很好的选择,比如日志系统、流水系统、云服务系统。- 如果你的业务需要支持复杂的事务查询、对ACID要求很高,那么结构化的mysql能够为你提供强大的能力支持,比如银行资金系统、火车票订单系统。- 不过,大部分情况下,并不需要选择,常用的后台管理系统、记账系统等用户量不高、只有存储需求的场景,mongodb和mysql都是可以满足需求的。- 另外,mysql和mongodb也经常一起使用,比如把mysql作为主库,由于其本身结构化特点,对于后期维护的技术债成本会比较低,而mongodb天然的面向对象设计,作为缓存数据库,也是可以带来很大的收益的。

补充

Redis也是常用的数据库,它跟mongodb一样,也是NoSql的一种,但它不是文档型的,而是基于键值对的。redis的数据是存储在内存中的,所以其优点很明显,读写性能极高,缺点也很明显,使用空间很小,所以一般的使用场景都是用来存放用户信息这类读写频率高、数据量不大的场景。

参考资料

juejin.cn/post/694981…

baijiahao.baidu.com/s?id=167298…

www.wbolt.com/mongodb-vs-…

zhuanlan.zhihu.com/p/70895268

juejin.cn/post/684490…