Python学习web框架开发

Flask SQL性能测试:使用flask-sqlalchemy

2021-01-14  本文已影响0人  xiaogp

摘要:Flaskflask-sqlalchemySQL

记录SQL语句和执行时长

flask-sqlalchemy可以记录下在客户端请求应用的过程中,后台涉及的SQL语句,以及SQL语句执行的时长,主要基于flask-sqlalchemy下的get_debug_queries实现。在主视图脚本中加入一个after_request视图如下。

import logging

from flask import Flask
from flask_sqlalchemy import get_debug_queries

import config
from blueprints.detail import detail
from blueprints.index import index
from blueprints.compare import compare
from external import db

logging .basicConfig(level=logging.DEBUG, filemode='a+', filename='query_log.log', format='%(asctime)s -: %(message)s)')
app = Flask(__name__)

app.config.from_object(config)
app.config['SQLALCHEMY_RECORD_QUERIES'] = True
db.init_app(app)
with app.app_context():
    db.create_all()


app.register_blueprint(index)
app.register_blueprint(compare)
app.register_blueprint(detail)


@app.after_request
def after_request(response):
    for query in get_debug_queries():
        if query.duration >= 0.2:
            logging.info('----------Slow query:' + query.statement)
            logging.info('----------duration:{}'.format(query.duration))
    return response


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=False)

其中开启SQL Debug模式app.config['SQLALCHEMY_RECORD_QUERIES'] = Trueget_debug_queries返回请求涉及的所有SQL语句,调用duration获得SQL执行时长,只要大于0.2就用logging模块记录到磁盘。
启动程序,点击应用功能,logging会把大于时间阈值的SQL写入本地文件query_log.log

查看SQL执行日志

直接搜索Slow query,得到以下几条记录

2021-01-14 16:20:11,073 -: ----------Slow query:SELECT pira_ent_alias.id AS pira_ent_alias_id, pira_ent_alias.ent_name AS pira_ent_alias_ent_name, pira_ent_alias.ent_shortname AS pira_ent_alias_ent_shortname, pira_ent_alias.score AS pira_ent_alias_score 
FROM pira_ent_alias 
WHERE pira_ent_alias.ent_name = %(ent_name_1)s)
2021-01-14 16:20:11,073 -: ----------duration:18.175966024398804)
2021-01-14 16:17:56,025 -: ----------Slow query:SELECT pira_score.id AS pira_score_id, pira_score.ent_name AS pira_score_ent_name, pira_score.score AS pira_sc
ore_score, pira_score.datetime AS pira_score_datetime, pira_score.industry AS pira_score_industry, pira_score.`rank` AS pira_score_rank 
FROM pira_score 
WHERE pira_score.ent_name = %(ent_name_1)s ORDER BY pira_score.datetime DESC 
 LIMIT %(param_1)s)
2021-01-14 16:17:56,025 -: ----------duration:7.9724133014678955)
2021-01-14 17:12:27,242 -: ----------Slow query:SELECT sum(pira_senti_stats.bad) AS sum_1, sum(pira_senti_stats.median) AS sum_2, sum(pira_senti_stats.good) A
S sum_3 
FROM pira_senti_stats 
WHERE pira_senti_stats.ent_name = %(ent_name_1)s AND pira_senti_stats.datetime <= %(datetime_1)s AND pira_senti_stats.datetime > %(datetime_2)s)
2021-01-14 17:12:27,242 -: ----------duration:4.695176601409912)

三张表pira_ent_alias,pira_score,pira_senti_stats都是简单的filter查询,没有复杂的逻辑,查看MySQL explain执行计划

mysql> EXPLAIN(SELECT pira_score.id AS pira_score_id, pira_score.ent_name AS pira_score_ent_name, pira_score.score AS pira_score_score, pira_score.datetime AS pira_score_datetime, pira_score.industry AS pira_score_industry, pira_score.`rank` AS pira_score_rank FROM pira_score WHERE pira_score.ent_name = '华为技术有限公司' ORDER BY pira_score.datetime DESC limit 15);
+----+-------------+------------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+
| id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra                       |
+----+-------------+------------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+
|  1 | SIMPLE      | pira_score | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 141355 |    10.00 | Using where; Using filesort |
+----+-------------+------------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+
mysql> EXPLAIN(SELECT pira_ent_alias.id AS pira_ent_alias_id, pira_ent_alias.ent_name AS pira_ent_alias_ent_name, pira_ent_alias.ent_shortname AS pira_ent_alias_ent_shortname, pira_ent_alias.score AS pira_ent_alias_score FROM pira_ent_alias WHERE pira_ent_alias.ent_name = '华为技术有限公司');
+----+-------------+----------------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table          | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra       |
+----+-------------+----------------+------------+------+---------------+------+---------+------+--------+----------+-------------+
|  1 | SIMPLE      | pira_ent_alias | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 415831 |    10.00 | Using where |
+----+-------------+----------------+------------+------+---------------+------+---------+------+--------+----------+-------------+
mysql> EXPLAIN(SELECT sum(pira_senti_stats.bad) AS sum_1, sum(pira_senti_stats.median) AS sum_2, sum(pira_senti_stats.good) AS sum_3  FROM pira_senti_stats  WHERE pira_senti_stats.ent_name = '华为技术有限公司' AND pira_senti_stats.datetime <= '2020-12-07' AND pira_senti_stats.datetime > '2020-06-07');
+----+-------------+------------------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table            | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra       |
+----+-------------+------------------+------------+------+---------------+------+---------+------+--------+----------+-------------+
|  1 | SIMPLE      | pira_senti_stats | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 167504 |     1.11 | Using where |
+----+-------------+------------------+------------+------+---------------+------+---------+------+--------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

explain结果解析

增加索引
三张表都进行了全表扫描,先加上索引再说,给pira_ent_alias增加ent_name和ent_shortname的普通索引

mysql> alter table pira_ent_alias  add index ent_name_index (ent_name);
Query OK, 0 rows affected (14.65 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table pira_ent_alias add index ent_shortname_index (ent_shortname);
Query OK, 0 rows affected (13.09 sec)
Records: 0  Duplicates: 0  Warnings: 0
mysql> EXPLAIN(SELECT pira_ent_alias.id AS pira_ent_alias_id, pira_ent_alias.ent_name AS pira_ent_alias_ent_name, pira_ent_alias.ent_shortname AS pira_ent_alias_ent_shortname, pira_ent_alias.score AS pira_ent_alias_score FROM pira_ent_alias WHERE pira_ent_alias.ent_name = '华为技术有限公司');
+----+-------------+----------------+------------+------+----------------+----------------+---------+-------+------+----------+-------+
| id | select_type | table          | partitions | type | possible_keys  | key            | key_len | ref   | rows | filtered | Extra |
+----+-------------+----------------+------------+------+----------------+----------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | pira_ent_alias | NULL       | ref  | ent_name_index | ent_name_index | 602     | const |    4 |   100.00 | NULL  |
+----+-------------+----------------+------------+------+----------------+----------------+---------+-------+------+----------+-------+

给pira_score,pira_senti_stats增加ent_name和datetime的复合索引,复合索引从字段组合的最左边开始就要走,否则无效,因此如果filter条件只有datetime还是全表扫描,filter条件是ent_name或者ent_name和datetime有效。

mysql> alter table pira_score add index ent_name_datetime_index(ent_name, datetime);
Query OK, 0 rows affected (12.43 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> EXPLAIN(SELECT pira_score.id AS pira_score_id, pira_score.ent_name AS pira_score_ent_name, pira_score.score AS pira_score_score, pira_score.datetime AS pira_score_datetime, pira_score.industry AS pira_score_industry, pira_score.`rank` AS pira_score_rank FROM pira_score WHERE pira_score.ent_name = '华为技术有限公司' ORDER BY pira_score.datetime DESC limit 15);
+----+-------------+------------+------------+------+-------------------------+-------------------------+---------+-------+------+----------+-------------+
| id | select_type | table      | partitions | type | possible_keys           | key                     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+------------+------------+------+-------------------------+-------------------------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | pira_score | NULL       | ref  | ent_name_datetime_index | ent_name_datetime_index | 602     | const |   38 |   100.00 | Using where |
+----+-------------+------------+------------+------+-------------------------+-------------------------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
mysql> alter table pira_senti_stats add index ent_name_datetime_index(ent_name, datetime);
Query OK, 0 rows affected (7.31 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> EXPLAIN(SELECT sum(pira_senti_stats.bad) AS sum_1, sum(pira_senti_stats.median) AS sum_2, sum(pira_senti_stats.good) AS sum_3  FROM pira_senti_stats  WHERE pira_senti_stats.ent_name = '华为技术有限公司' AND pira_senti_stats.datetime <= '2020-12-07' AND pira_senti_stats.datetime > '2020-06-07');
+----+-------------+------------------+------------+-------+-------------------------+-------------------------+---------+------+------+----------+-----------------------+
| id | select_type | table            | partitions | type  | possible_keys           | key                     | key_len | ref  | rows | filtered | Extra                 |
+----+-------------+------------------+------------+-------+-------------------------+-------------------------+---------+------+------+----------+-----------------------+
|  1 | SIMPLE      | pira_senti_stats | NULL       | range | ent_name_datetime_index | ent_name_datetime_index | 664     | NULL |  158 |   100.00 | Using index condition |
+----+-------------+------------------+------------+-------+-------------------------+-------------------------+---------+------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)

对比SQL性能优化

给三张表增加索引之后,再次运行get_debug_queries,阈值降低为0,查看日志如下,执行时间都有很大降低

2021-01-14 17:39:35,356 -: ----------Slow query:SELECT pira_ent_alias.id AS pira_ent_alias_id, pira_ent_alias.ent_name AS pira_ent_alias_ent_name, pira_ent_alias.ent_shortname AS pira_ent_alias_ent_shortname, pira_ent_alias.score AS pira_ent_alias_score 
FROM pira_ent_alias 
WHERE pira_ent_alias.ent_name = %(ent_name_1)s)
2021-01-14 17:39:35,356 -: ----------duration:0.024198293685913086)
2021-01-14 17:39:35,356 -: ----------Slow query:SELECT pira_score.id AS pira_score_id, pira_score.ent_name AS pira_score_ent_name, pira_score.score AS pira_score_score, pira_score.datetime AS pira_score_datetime, pira_score.industry AS pira_score_industry, pira_score.`rank` AS pira_score_rank 
FROM pira_score 
WHERE pira_score.ent_name = %(ent_name_1)s ORDER BY pira_score.datetime DESC 
 LIMIT %(param_1)s)
2021-01-14 17:39:35,356 -: ----------duration:0.003040790557861328)
2021-01-14 17:39:35,356 -: ----------Slow query:SELECT sum(pira_senti_stats.bad) AS sum_1, sum(pira_senti_stats.median) AS sum_2, sum(pira_senti_stats.good) AS sum_3 
FROM pira_senti_stats 
WHERE pira_senti_stats.ent_name = %(ent_name_1)s AND pira_senti_stats.datetime <= %(datetime_1)s AND pira_senti_stats.datetime > %(datetime_2)s)
2021-01-14 17:39:35,356 -: ----------duration:0.0028617382049560547)
上一篇下一篇

猜你喜欢

热点阅读