django页面请求sql分析中间件
django页面请求sql分析中间件
农村程序员 发表于3年前
django页面请求sql分析中间件
  • 发表于 3年前
  • 阅读 41
  • 收藏 5
  • 点赞 0
  • 评论 0

移动开发云端新模式探索实践 >>>   

很久没有写博客了,记录一些东西吧

写django程序时由于直接和django model交互,对sql的操作不是那么直观。所以很容易造成一些sql查询问题。

如常见的sql分页位置不正确导致查询整个表,多次queryset没有利用缓存导致多次sql重复查询等。之前一直用打印的方式查询,感觉还是不够方便。

于是有了下面的sql中间件,在本地开发时每次输出sql的一些简单分析信息提供参考

class DjangoSqlInspectMiddleware(object):

    def process_request(self, request):
        self.start_end_chars_dict = {'start_chars': '<' * 20, 'end_chars': '>' * 20}

        self.start = time.time()
        logger.info(os.linesep * 4)
        logger.info('%(start_chars)s sql analyse start %(end_chars)s' % self.start_end_chars_dict)

    def process_response(self, request, response):
        sqltime_list = connection.queries
        pprint.pprint(sqltime_list)

        duplicate_sqltime_dict = defaultdict(int)
        sql_total_time = 0
        max_sqltime, min_sqltime = (None,) * 2
        for st in sqltime_list:
            sql = st['sql']
            sql_total_time += float(st['time'])
            duplicate_sqltime_dict[sql] = duplicate_sqltime_dict[sql] + 1
            if not max_sqltime or not min_sqltime:
                max_sqltime = min_sqltime = st
            else:
                t = st['time']
                if t > max_sqltime['time']:
                    max_sqltime = st
                if t < min_sqltime['time']:
                    min_sqltime = st

        self.end = time.time()
        consume_time = self.end - self.start
        logger.info('[SQL] %s queries, %s SQL time, %s total request time' %
                    (len(duplicate_sqltime_dict), sql_total_time, consume_time))

        logger.info('[MAX TIME]: %s seconds' % (max_sqltime['time'], ))
        logger.info('[MAX TIME SQL]:%s %s' % (os.linesep, max_sqltime['sql']))

        logger.info('[MIN TIME]: %s seconds' % min_sqltime['time'])
        logger.info('[MIN TIME SQL]:%s %s' % (os.linesep, min_sqltime['sql']))

        logger.info('[CHECK DUPLICATE]:')
        for k, v in duplicate_sqltime_dict.iteritems():
            if v > 1:
                logger.info('(%s)' % v + k)
                logger.info('---------------------------------------------')
        logger.info('%(start_chars)s sql analyse end %(end_chars)s' % self.start_end_chars_dict)
        logger.info(os.linesep * 2)
        return response

主要程序如上, 如果感兴趣的同学可以在github上一起完善或者有更好的方式给予建议哈

https://github.com/lyroge/django-sqlinspect

  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 13
博文 14
码字总数 7273
×
农村程序员
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: