http://blog.163.com/pjt_ren/blog/static/188250602014121103854532/
MySql一直是性价比最高的关系型数据库典范
MongoDB带来了关系数据库以外的NoSql体验。
让我们看一个简单的例子,我们将如何为MySQL(或任何关系数据库)和MongoDB中创建一个数据结构。
MySql设计
我们假设设计个表:
People 人物信息表 包含ID 和名字字段
passports 护照表 ,主要包含 对应的people表的外键ID ,所属国家,和护照有效期
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
mysql
>
select
*
from
people
;
+
--
--
+
--
--
--
--
--
--
+
|
id
|
name
|
+
--
--
+
--
--
--
--
--
--
+
|
1
|
Stephane
|
|
2
|
John
|
|
3
|
Michael
|
|
4
|
Cinderella
|
+
--
--
+
--
--
--
--
--
--
+
mysql
>
select
*
from
passports
;
+
--
--
+
--
--
--
--
--
-
+
--
--
--
--
-
+
--
--
--
--
--
--
-
+
|
id
|
people_id
|
country
|
valid_until
|
+
--
--
+
--
--
--
--
--
-
+
--
--
--
--
-
+
--
--
--
--
--
--
-
+
|
4
|
1
|
FR
|
2020
-
01
-
01
|
|
5
|
2
|
US
|
2020
-
01
-
01
|
|
6
|
3
|
RU
|
2020
-
01
-
01
|
+
--
--
+
--
--
--
--
--
-
+
--
--
--
--
-
+
--
--
--
--
--
--
-
+
|
于是你接下来可以操作如下基本功能:
一共有多少人
1
|
SELECT
count
(
*
)
FROM
people
|
查询出 stephane 的护照有效期
1
|
SELECT
valid_until
from
passports
ps
join
people
pl
ON
ps
.
people_id
=
pl
.
id
WHERE
name
=
'Stephane'
|
有多少人木有护照
1
|
SELECT
name
FROM
people
pl
LEFT
JOIN
passports
ps
ON
ps
.
people_id
=
pl
.
id
WHERE
ps
.
id
IS
NULL
|
MongoDB的设计
接下来是在MongoDB中进行设计
上述关系型数据库中使用三范式,固然是规范的,但是效率不高,因为关联度不高的情况下完全没有必要使用三范式来设计。
一种是“直筒式”的设计,和关系型数据库的理解区别不大
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
{
"_id"
:
ObjectId
(
"51f7be1cd6189a56c399d3bf"
)
,
"name"
:
"Stephane"
,
"country"
:
"FR"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
}
{
"_id"
:
ObjectId
(
"51f7be3fd6189a56c399d3c0"
)
,
"name"
:
"John"
,
"country"
:
"US"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
}
{
"_id"
:
ObjectId
(
"51f7be4dd6189a56c399d3c1"
)
,
"name"
:
"Michael"
,
"country"
:
"RU"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
}
{
"_id"
:
ObjectId
(
"51f7be5cd6189a56c399d3c2"
)
,
"name"
:
"Cinderella"
}
|
MongoDB 无固定结构,每张表每段数据可以有不同的结构,这既是好处也是缺点,缺点在于你必须很了解MongoDB的表结构,这其实给维护人员带来一定的不适应和麻烦。
2、以下是MongoDb特征的设计方法, 既:把people信息和护照信息柔和在一起
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
{
"_id"
:
ObjectId
(
"51f7c0048ded44d5ebb83774"
)
,
"name"
:
"Stephane"
,
"passport"
:
{
"country"
:
"FR"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
}
}
{
"_id"
:
ObjectId
(
"51f7c70e8ded44d5ebb83775"
)
,
"name"
:
"John"
,
"passport"
:
{
"country"
:
"US"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
}
}
{
"_id"
:
ObjectId
(
"51f7c71b8ded44d5ebb83776"
)
,
"name"
:
"Michael"
,
"passport"
:
{
"country"
:
"RU"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
}
}
{
"_id"
:
ObjectId
(
"51f7c7258ded44d5ebb83777"
)
,
"name"
:
"Cinderella"
}
|
3、同样的,上述结构也可以字段反过来设计,如果没有“valid_until”字段代表没有护照
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
{
"_id"
:
ObjectId
(
"51f7c7e58ded44d5ebb8377b"
)
,
"country"
:
"FR"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
,
"person"
:
{
"name"
:
"Stephane"
}
}
{
"_id"
:
ObjectId
(
"51f7c7ec8ded44d5ebb8377c"
)
,
"country"
:
"US"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
,
"person"
:
{
"name"
:
"John"
}
}
{
"_id"
:
ObjectId
(
"51f7c7fa8ded44d5ebb8377d"
)
,
"country"
:
"RU"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
,
"person"
:
{
"name"
:
"Michael"
}
}
{
"_id"
:
ObjectId
(
"51f7c8058ded44d5ebb8377e"
)
,
"person"
:
{
"name"
:
"Cinderella"
}
}
|
结论
我们看到MySQL和MongoDB的根本区别之一,
1、使用MongoDB, 架构设计变得无比重要,一旦中间有个环节设计的有问题,将会带来灾难性的维护和返工后果,后面更不用提优化。但是同样的问题也逼着我们去做一个好的架构养成好的习惯。
2、 哪种方式更好?当然,有没有明确的答案。不同的环境使用不同的方式,就像上面这个例子完全使用MongoDB效率更高,譬如单表数据达到1000 万,mysql关联查询是很坑爹的。对于多业务逻辑复杂关联设计,MongoDB不是不能胜任,关键我们不能保证我们的软件需求像老外那样不会一直变更或 者推翻重写,所以用mysql更易于维护
MySql一直是性价比最高的关系型数据库典范
MongoDB带来了关系数据库以外的NoSql体验。
让我们看一个简单的例子,我们将如何为MySQL(或任何关系数据库)和MongoDB中创建一个数据结构。
MySql设计
我们假设设计个表:
People 人物信息表 包含ID 和名字字段
passports 护照表 ,主要包含 对应的people表的外键ID ,所属国家,和护照有效期
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
mysql
>
select
*
from
people
;
+
--
--
+
--
--
--
--
--
--
+
|
id
|
name
|
+
--
--
+
--
--
--
--
--
--
+
|
1
|
Stephane
|
|
2
|
John
|
|
3
|
Michael
|
|
4
|
Cinderella
|
+
--
--
+
--
--
--
--
--
--
+
mysql
>
select
*
from
passports
;
+
--
--
+
--
--
--
--
--
-
+
--
--
--
--
-
+
--
--
--
--
--
--
-
+
|
id
|
people_id
|
country
|
valid_until
|
+
--
--
+
--
--
--
--
--
-
+
--
--
--
--
-
+
--
--
--
--
--
--
-
+
|
4
|
1
|
FR
|
2020
-
01
-
01
|
|
5
|
2
|
US
|
2020
-
01
-
01
|
|
6
|
3
|
RU
|
2020
-
01
-
01
|
+
--
--
+
--
--
--
--
--
-
+
--
--
--
--
-
+
--
--
--
--
--
--
-
+
|
于是你接下来可以操作如下基本功能:
一共有多少人
1
|
SELECT
count
(
*
)
FROM
people
|
查询出 stephane 的护照有效期
1
|
SELECT
valid_until
from
passports
ps
join
people
pl
ON
ps
.
people_id
=
pl
.
id
WHERE
name
=
'Stephane'
|
有多少人木有护照
1
|
SELECT
name
FROM
people
pl
LEFT
JOIN
passports
ps
ON
ps
.
people_id
=
pl
.
id
WHERE
ps
.
id
IS
NULL
|
MongoDB的设计
接下来是在MongoDB中进行设计
上述关系型数据库中使用三范式,固然是规范的,但是效率不高,因为关联度不高的情况下完全没有必要使用三范式来设计。
一种是“直筒式”的设计,和关系型数据库的理解区别不大
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
{
"_id"
:
ObjectId
(
"51f7be1cd6189a56c399d3bf"
)
,
"name"
:
"Stephane"
,
"country"
:
"FR"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
}
{
"_id"
:
ObjectId
(
"51f7be3fd6189a56c399d3c0"
)
,
"name"
:
"John"
,
"country"
:
"US"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
}
{
"_id"
:
ObjectId
(
"51f7be4dd6189a56c399d3c1"
)
,
"name"
:
"Michael"
,
"country"
:
"RU"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
}
{
"_id"
:
ObjectId
(
"51f7be5cd6189a56c399d3c2"
)
,
"name"
:
"Cinderella"
}
|
MongoDB 无固定结构,每张表每段数据可以有不同的结构,这既是好处也是缺点,缺点在于你必须很了解MongoDB的表结构,这其实给维护人员带来一定的不适应和麻烦。
2、以下是MongoDb特征的设计方法, 既:把people信息和护照信息柔和在一起
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
{
"_id"
:
ObjectId
(
"51f7c0048ded44d5ebb83774"
)
,
"name"
:
"Stephane"
,
"passport"
:
{
"country"
:
"FR"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
}
}
{
"_id"
:
ObjectId
(
"51f7c70e8ded44d5ebb83775"
)
,
"name"
:
"John"
,
"passport"
:
{
"country"
:
"US"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
}
}
{
"_id"
:
ObjectId
(
"51f7c71b8ded44d5ebb83776"
)
,
"name"
:
"Michael"
,
"passport"
:
{
"country"
:
"RU"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
}
}
{
"_id"
:
ObjectId
(
"51f7c7258ded44d5ebb83777"
)
,
"name"
:
"Cinderella"
}
|
3、同样的,上述结构也可以字段反过来设计,如果没有“valid_until”字段代表没有护照
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
{
"_id"
:
ObjectId
(
"51f7c7e58ded44d5ebb8377b"
)
,
"country"
:
"FR"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
,
"person"
:
{
"name"
:
"Stephane"
}
}
{
"_id"
:
ObjectId
(
"51f7c7ec8ded44d5ebb8377c"
)
,
"country"
:
"US"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
,
"person"
:
{
"name"
:
"John"
}
}
{
"_id"
:
ObjectId
(
"51f7c7fa8ded44d5ebb8377d"
)
,
"country"
:
"RU"
,
"valid_until"
:
ISODate
(
"2019-12-31T23:00:00Z"
)
,
"person"
:
{
"name"
:
"Michael"
}
}
{
"_id"
:
ObjectId
(
"51f7c8058ded44d5ebb8377e"
)
,
"person"
:
{
"name"
:
"Cinderella"
}
}
|
结论
我们看到MySQL和MongoDB的根本区别之一,
1、使用MongoDB, 架构设计变得无比重要,一旦中间有个环节设计的有问题,将会带来灾难性的维护和返工后果,后面更不用提优化。但是同样的问题也逼着我们去做一个好的架构养成好的习惯。
2、 哪种方式更好?当然,有没有明确的答案。不同的环境使用不同的方式,就像上面这个例子完全使用MongoDB效率更高,譬如单表数据达到1000 万,mysql关联查询是很坑爹的。对于多业务逻辑复杂关联设计,MongoDB不是不能胜任,关键我们不能保证我们的软件需求像老外那样不会一直变更或 者推翻重写,所以用mysql更易于维护