会用JOIN,却不懂编程的“程序员”(6)

HH MySQL python1 7,9462字数 3736阅读12分27秒阅读模式

1.1. 前言

之前的文章应该已经是彻彻底底的证明的拆分join带来的好处是极大的,并且基本已经打破了一些人的谣言。那(“装饰器”+“拆分JOIN”)就这些能耐了吗?答案是否定的。让我们来看一下基本上在每个项目中都是要做的。

1.2. 场景

随着项目的发展需要对业务进行切割。如将“商品管理”和“订单管理”进行分开。这里的分开是在“程序”和“数据库”同事切分。这时候商品数据和订单数据都不是在同一个库因此要做到跨库查询。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

大多的项目说到要项目切割的时候,那基本上就是一个噩梦。基本上就是需要对项目进行重构,重新开放了。就想我再公司说,这个表已经过大,需要拆分,程序员总是说:“这个改动太大”一样。一看改动太大的原因是因为,他们的代码中对数据库的操作充满的join,因此,他们说的改动太大这是肯定的。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

1.3. 装饰器完成跨库表查询

我们现在模拟券表(coupon)在test1数据库中。数据为:文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

SELECT * FROM coupon;
+-----------+----------+-----------+
| coupon_id | order_id | name      |
+-----------+----------+-----------+
|         1 |        1 | coupon_7  |
|         2 |        3 | coupon_9  |
|         3 |        5 | coupon_11 |
+-----------+----------+-----------+

和之前一样我们,使用的是(“装饰器”+“拆分JOIN”)的方法。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

1.4. 实现程序

这里我们在创建一个装饰器方法use_db,这个方法可以传入一个参数conn:文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

conn:数据库的链接。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

之后我们在get_coupon_info方法上面添加一个annotation:@use_db(conn=conn1),其中conn1代表数据库test1的链接。这样之后查找券的信息就是在test1中查找的了。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

代码如下:文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

#!/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()

输出结果:文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

 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文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

从上面可以看到最后一列的券的信息,就是从test1库的coupon表关联来的。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

1.5. 总结

通过系列文章的介绍我们知道拆分jion将会给我们带来各种的好处。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

通过查分jion之后我们会看到系统现象是,应用程序的CPU利用率会上去。而数据库的CPU会下来,这也是我们想要的结果。如果一个应用程序CPU太高了你可以扩展多个应用程序。这中架构也是我们想要的。如果是使用JION那数据库的CPU上去了。我们将会很难扩展,并且扩展的成本、人力和物力将会是层倍的增加都不止。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

到了这里,如果你还是觉得jion比拆分jion的效率高,代码量大的话。我只能说对不起了:我只是一个不称职的DBA,一个不懂得写复杂SQL的DBA。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

以上乃个人观点。如果有得罪到大神们的地方,在这里我对你们说对不起,请原谅小菜鸟我的无知。当然,我更喜欢的是交朋友。有什么问题或不好的请多多指教。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

 文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

昵称:HH
QQ:275258836
ttlsa群交流沟通(QQ群②:6690706 QQ群③:168085569 QQ群④:415230207(新) 微信公众号:ttlsacom)文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

感觉本文内容不错,读后有收获?文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

逛逛衣服店,鼓励作者写出更好文章。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/ 文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_6/

weinxin
我的微信
微信公众号
扫一扫关注运维生存时间公众号,获取最新技术文章~
HH
  • 本文由 发表于 17/05/2016 00:44:43
  • 转载请务必保留本文链接:https://www.ttlsa.com/mysql/using_join_no_programing_6/
评论  1  访客  1
    • meike
      meike 0

      想问一下如果原来是多表联合查询得到分页的结果,那你以那个表作为基准取出需要分页的条数呢?

    评论已关闭!