1.1. 前言
之前的文章应该已经是彻彻底底的证明的拆分join带来的好处是极大的,并且基本已经打破了一些人的谣言。那(“装饰器”+“拆分JOIN”)就这些能耐了吗?答案是否定的。让我们来看一下基本上在每个项目中都是要做的。
1.2. 场景
随着项目的发展需要对业务进行切割。如将“商品管理”和“订单管理”进行分开。这里的分开是在“程序”和“数据库”同事切分。这时候商品数据和订单数据都不是在同一个库因此要做到跨库查询。
大多的项目说到要项目切割的时候,那基本上就是一个噩梦。基本上就是需要对项目进行重构,重新开放了。就想我再公司说,这个表已经过大,需要拆分,程序员总是说:“这个改动太大”一样。一看改动太大的原因是因为,他们的代码中对数据库的操作充满的join,因此,他们说的改动太大这是肯定的。
1.3. 装饰器完成跨库表查询
我们现在模拟券表(coupon)在test1数据库中。数据为:
1
2
3
4
5
6
7
8
|
SELECT *
FROM
coupon
;
+
--
--
--
--
--
-
+
--
--
--
--
--
+
--
--
--
--
--
-
+
|
coupon_id
|
order_id
|
name
|
+
--
--
--
--
--
-
+
--
--
--
--
--
+
--
--
--
--
--
-
+
|
1
|
1
|
coupon_7
|
|
2
|
3
|
coupon_9
|
|
3
|
5
|
coupon_11
|
+
--
--
--
--
--
-
+
--
--
--
--
--
+
--
--
--
--
--
-
+
|
和之前一样我们,使用的是(“装饰器”+“拆分JOIN”)的方法。
1.4. 实现程序
这里我们在创建一个装饰器方法use_db,这个方法可以传入一个参数conn:
conn:数据库的链接。
之后我们在get_coupon_info方法上面添加一个annotation:@use_db(conn=conn1),其中conn1代表数据库test1的链接。这样之后查找券的信息就是在test1中查找的了。
代码如下:
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import
pandas
as
pd
import
mysql
.
connector
import
sys
reload
(
sys
)
sys
.
setdefaultencoding
(
'utf-8'
)
conf
=
{
'host'
:
'127.0.0.1'
,
'port'
:
'3306'
,
'database'
:
'test'
,
'user'
:
'root'
,
'password'
:
'root'
}
conn
=
mysql
.
connector
.
connect
(
*
*
conf
)
conf1
=
{
'host'
:
'127.0.0.1'
,
'port'
:
'3306'
,
'database'
:
'test1'
,
'user'
:
'root'
,
'password'
:
'root'
}
conn1
=
mysql
.
connector
.
connect
(
*
*
conf1
)
def
use_db
(
conn
=
None
)
:
''
'
选择使用的db conn
'
''
def
_use_db
(
func
)
:
def
__use_db
(
*
args
,
*
*
kargs
)
:
func_info
=
func
(
*
args
,
conn
=
conn
)
return
func_info
return
__use_db
return
_use_db
def
get_user_info
(
user_ids
,
conn
=
None
)
:
''
'
通过user_id获得用户信息
'
''
user_sql
=
''
'
SELECT user_id, name FROM user WHERE user_id IN({user_ids});
'
''
.
format
(
user_ids
=
','
.
join
(
user_ids
)
)
user_info
=
pd
.
read_sql
(
user_sql
,
conn
)
return
user_info
def
get_order_info
(
user_ids
,
conn
=
None
)
:
''
'
通过 用户ID 获得订单信息
'
''
order_sql
=
''
'
SELECT user_id, order_id, num FROM orders WHERE user_id IN({user_ids});
'
''
.
format
(
user_ids
=
','
.
join
(
user_ids
)
)
order_info
=
pd
.
read_sql
(
order_sql
,
conn
)
return
order_info
def
get_order_good_info
(
order_ids
,
conn
=
None
)
:
''
'
通过上面获得的 订单ID 获得订单商品信息。
'
''
order_good_sql
=
''
'
SELECT order_id, good_name FROM order_good WHERE order_id IN ({ids});
'
''
.
format
(
ids
=
','
.
join
(
order_ids
)
)
order_good_info
=
pd
.
read_sql
(
order_good_sql
,
conn
)
return
order_good
_info
@
use_db
(
conn
=
conn1
)
def
get_coupon_info
(
order_ids
,
conn
=
None
)
:
''
'
通过 订单ID 获得券信息
'
''
coupon_sql
=
''
'
SELECT order_id, name FROM coupon WHERE order_id IN({ids});
'
''
.
format
(
ids
=
','
.
join
(
order_ids
)
)
coupon_info
=
pd
.
read_sql
(
coupon_sql
,
conn
)
return
coupon_info
def
join_data
(
func_name
,
col_name
)
:
''
'
添加能通过订单ID查找出来的信息
'
''
def
_join_data
(
func
)
:
def
__join_data
(
*
args
,
*
*
kargs
)
:
func_info
=
func
(
*
args
,
*
*
kargs
)
ids
=
func_info
[
col_name
]
.
astype
(
str
)
info
=
eval
(
func_name
)
(
ids
,
*
*
kargs
)
new_order
=
func_info
.
merge
(
info
,
left_on
=
col_name
,
right_on
=
col_name
,
how
=
'left'
)
return
new_order
return
__join_data
return
_join
_data
@
join_data
(
'get_coupon_info'
,
'order_id'
)
@
join_data
(
'get_order_good_info'
,
'order_id'
)
@
join_data
(
'get_order_info'
,
'user_id'
)
def
get_order_detail
(
user_id
,
conn
=
None
)
:
''
'
拼凑获得订单信息
'
''
user_ids
=
[
str
(
user_id
)
]
return
get_user_info
(
user_ids
,
conn
=
conn
)
if
__name__
==
'__main__'
:
print
get_order_detail
(
10
,
conn
=
conn
)
conn
.
close
(
)
|
输出结果:
1
2
3
4
5
6
7
8
9
10
11
|
user_id
name_x
order_id
num
good_name
name
_y
0
10
HH
1
11111
order_good_1
coupon
_7
1
10
HH
1
11111
order_good_2
coupon
_7
2
10
HH
2
22222
order_good_3
NaN
3
10
HH
2
22222
order_good_4
NaN
4
10
HH
3
33333
order_good_5
coupon
_9
5
10
HH
3
33333
order_good_6
coupon
_9
6
10
HH
4
44444
order_good_7
NaN
7
10
HH
4
44444
order_good_8
NaN
8
10
HH
5
55555
order_good_9
coupon
_11
9
10
HH
5
55555
order_good_10
coupon_11
|
源代码:use_decorator_diff_db
从上面可以看到最后一列的券的信息,就是从test1库的coupon表关联来的。
1.5. 总结
通过系列文章的介绍我们知道拆分jion将会给我们带来各种的好处。
通过查分jion之后我们会看到系统现象是,应用程序的CPU利用率会上去。而数据库的CPU会下来,这也是我们想要的结果。如果一个应用程序CPU太高了你可以扩展多个应用程序。这中架构也是我们想要的。如果是使用JION那数据库的CPU上去了。我们将会很难扩展,并且扩展的成本、人力和物力将会是层倍的增加都不止。
到了这里,如果你还是觉得jion比拆分jion的效率高,代码量大的话。我只能说对不起了:我只是一个不称职的DBA,一个不懂得写复杂SQL的DBA。
以上乃个人观点。如果有得罪到大神们的地方,在这里我对你们说对不起,请原谅小菜鸟我的无知。当然,我更喜欢的是交朋友。有什么问题或不好的请多多指教。
昵称:HH
QQ:275258836
ttlsa群交流沟通(QQ群②:6690706 QQ群③:168085569 QQ群④:415230207(新) 微信公众号:ttlsacom)
感觉本文内容不错,读后有收获?
逛逛衣服店,鼓励作者写出更好文章。
转载请注明:成长的对话 » 会用JOIN,却不懂编程的“程序员”(6)