性能

记录影响性能的缓慢数据库查询

如果程序性能随着时间推移不断降低,那很有可能是因为数据库查询变慢了,随着数据库规模的增长,这一情况还会变得更糟,优化数据库有时很简单,只需添加更多的索引即可,有时也很复杂,需要在程序和数据库之前加入缓存,大多数数据库查询语言都提供了explain语句,用来显示数据库执行查询时采取的步骤,从这些步骤中,我们经常能发现数据库或索引设计的不足之处

不过,在开始优化查询之前,我们必须要知道哪些查询是值得优化的,在一次典型请求中,可能要执行多条数据库查询,所以经常很难分辨哪一条查询较慢,Flask-SQLAlchemy提供了一个选项,可以记录请求中执行的与数据库查询相关的统计数字,在下例中,我们可以看到如何使用这个功能把慢于设定阈值的查询写入日志

# app/main/views.py

from flasky_sqkalchemy import get_debug_queries

@main.after_app_request
def after_request(response):
    for query in get_debug_queries():
        if query.duration >= current_app.config['FLASKY_SLOW_DB_QUERY_TIME']:
            current_app.logger.warning(
                'Slow query: %s\nParameters: %s\nDuration: %fs\nContext: %s\n' (query.statement, query.parameters, query.duration,
                                                                                    query.context))
    return response

这个功能使用after_app_request处理程序实现,它和before_app_request处理程序的工作方式类似,只不过在视图函数处理完请求之后执行,Flask把响应对象传给after_app_request处理程序,以防需要修改响应

在本例中,after_app_request处理程序没有修改响应,只是获取Flask-SQLAlchemy记录的查询时间并把缓慢的查询写入日志

get_debug_queries()函数返回一个列表,其元素是请求中执行的查询,查询信息如下表:

名称说明
statementSQL语句
parametersSQL语句使用的参数
start_time执行查询时的时间
end_time返回查询结果时的时间
duration返回持续的时间,单位为秒
context表示查询在源码中所处位置的字符串

after_app_request处理程序遍历get_debus_queries()函数获取的列表,把持续时间比设定阈值长的查询写入日志,写入的日志被设为“警告”等级,如果换成“错误”等级,发现缓慢的查询时还会发送电子邮件

默认情况下,get_debug_queries()函数只在调试模式中可用,但是数据库性能问题很少发生在开发阶段,因为开发过程中使用的数据库较小,因此,在生产环境中使用该选项才能发挥作用,若想在生产环境中分析数据库性能,我们必须修改配置,如下:

class Config:

#...

    SQLALCHEMY_RECORD_QUERIES = True
    FLASKY_DB_QUERY_TIMEOUT = 0.5

#...

SQLALCHEMY_RECORD_QUERIES告诉Flask-SQLAlchemy启用记录查询统计数字的功能,缓慢查询的阈值设为0.5秒,这两个配置变量都在Config基类中设置,因此在所有环境中都可使用

每当发现缓慢查询,Flask程序的日志记录器就会写入一条记录,若想保存这些日志记录,必须配置日志记录器,日志记录器的配置根据程序所在主机使用的平台而有所不同

分析源码

性能问题的另一个可能诱因是高CPU消耗,由执行大量运算的函数导致,源码分析器能找出程序中执行最慢的部分,分析器监视运行中的程序,记录调用的函数以及运行各函数所消耗的时间,然后生成一份详细的报告,指出运行最慢的函数

分析一般在开发环境中进行,源码分析器会让程序运行得更慢,因为分析器要监视并记录程序中发生的一切,因此不建议在生产环境中进行分析,除非使用专为生产环境设计的轻量级分析器

Flask使用的开发Web服务器由Werkzeug提供,可根据需要为每条请求启用Python分析器,下例向程序中添加了一个新命令,用来启动分析器

# /manage.py
@manager.command
def profile(length=25, profile_dir=None):
    """Start the application under the code profile"""
    from werkzeug.contrib.profiler import ProfileMiddleware
    app.wsgi_app = ProfilerMiddleware(app.wsgi_app, restrictions=[length],
                                      profile_dir=profile_dir)

    app.run()

使用python manage.py profile启动程序后,终端会显示每条请求的分析数据,其中包含运行最慢的25个函数, --length选项可以修改报告中显示的函数数量,如果指定了 --profile -dir选项,每条请求的分析数据就会保存到指定目录下的一个文件中,分析器数据文件可用来生成更详细的报告,利用调用图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值