mysql depended_query 优化案例一则
月度利息统计sql优化
原因:写的sql语句复杂,理解起来有难度,另一方面,查询性能比较低
原来的语句如下:
SELECT
tp.year,
tp.month,
tp.bid_id,
b.`title`,
DATE(b.`time`) `time`,
tp.receive_date,
u.`name`,
u.`reality_name`,
b.`amount`,
b.`apr`,
b.`period_unit`,
b.`period`,
tp.receive_interest,
tp.bid_invest_count,
IFNULL((SELECT SUM(s.`amount`) FROM t_invests s WHERE s.`bid_id`=tp.bid_id AND s.user_id IN (SELECT r.user_id FROM `t_user_repair` r)), 0) AS bid_amount1,
IFNULL((SELECT SUM(s.`receive_corpus`) FROM t_bill_invests s WHERE s.`bid_id`=tp.bid_id AND DATE(IFNULL(s.`real_receive_time`, s.`receive_time`))=tp.`receive_date` AND s.user_id IN (SELECT r.user_id FROM `t_user_repair` r)), 0) AS bid_corpus1,
IFNULL((SELECT SUM(s.`receive_interest`) FROM t_bill_invests s WHERE s.`bid_id`=tp.bid_id AND DATE(IFNULL(s.`real_receive_time`, s.`receive_time`))=tp.`receive_date` AND s.user_id IN (SELECT r.user_id FROM `t_user_repair` r)), 0) AS bid_interest1,
IFNULL((SELECT COUNT(1) FROM t_bill_invests s WHERE s.`bid_id`=tp.bid_id AND DATE(IFNULL(s.`real_receive_time`, s.`receive_time`))=tp.`receive_date` AND s.user_id IN (SELECT r.user_id FROM `t_user_repair` r)), 0) AS bid_invest_count1,
IFNULL((SELECT SUM(s.`receive_corpus`) FROM t_bill_invests s WHERE s.`bid_id`=tp.bid_id AND DATE(IFNULL(s.`real_receive_time`, s.`receive_time`))=tp.`receive_date` AND s.user_id NOT IN (SELECT r.user_id FROM `t_user_repair` r)), 0) AS bid_corpus2
FROM
(
SELECT
t.`bid_id`,
DATE(IFNULL(t.`real_receive_time`, t.`receive_time`)) AS `receive_date`,
YEAR(IFNULL(t.`real_receive_time`, t.`receive_time`)) AS `year`,
MONTH(IFNULL(t.`real_receive_time`, t.`receive_time`)) AS `month`,
IFNULL(SUM(t.`receive_interest`),0) receive_interest,
COUNT(1) AS bid_invest_count
FROM t_bill_invests t
WHERE 1=1 AND DATE(IFNULL(t.`real_receive_time`, t.`receive_time`)) >= '2015-09-01' AND DATE(IFNULL(t.`real_receive_time`, t.`receive_time`)) <= '2015-10-31'
GROUP BY `year`, `month`, t.`bid_id`, DATE(IFNULL(t.`real_receive_time`, t.`receive_time`))
)tp
LEFT JOIN t_bids b ON tp.bid_id=b.`id`
LEFT JOIN t_users u ON b.`user_id`=u.`id`;
执行结果所需时间信息如下:
/* Affected rows: 0 已找到记录: 129 警告: 0 持续时间 1 query: 28.704 sec. (+ 10.031 sec. network) */
最终优化语句:
SELECT
YEAR(IFNULL(tp.`real_receive_time`, tp.`receive_time`)) AS `year`,
MONTH(IFNULL(tp.`real_receive_time`, tp.`receive_time`)) AS `month`,
tp.bid_id,
b.`title`,
DATE(b.`time`) `time`,
DATE(IFNULL(tp.`real_receive_time`, tp.`receive_time`)) AS `receive_date`,
u.`name`,
u.`reality_name`,
b.`amount`,
b.`apr`,
b.`period_unit`,
b.`period`,
sum(if(tp.real_receive_time,tp.`receive_interest`,0)) receive_interest,
COUNT(1) AS bid_invest_count ,
sum(if(tp.user_id in (SELECT r.user_id FROM `t_user_repair` r) and tp.real_receive_time is not null,ti.amount,0 )) bid_amount1,
sum(if(tp.user_id in (SELECT r.user_id FROM `t_user_repair` r) and tp.real_receive_time is not null,tp.receive_corpus,0 )) bid_corpus1,
sum(if(tp.user_id in (SELECT r.user_id FROM `t_user_repair` r) and tp.real_receive_time is not null,tp.receive_interest,0 )) bid_interest1,
sum(if(tp.user_id in (SELECT r.user_id FROM `t_user_repair` r),1,0 )) bid_invest_count1,
sum(if(tp.user_id not in (SELECT r.user_id FROM `t_user_repair` r) and tp.real_receive_time is not null,tp.receive_corpus,0 )) bid_corpus2
FROM t_bill_invests tp
LEFT JOIN t_bids b ON tp.bid_id=b.`id`
LEFT JOIN t_users u ON b.`user_id`=u.`id`
left join (select id,amount from t_invests) ti on ti.id=tp.invest_id
WHERE 1=1 AND DATE(IFNULL(tp.`real_receive_time`, tp.`receive_time`)) >= '2015-09-01' AND DATE(IFNULL(tp.`real_receive_time`, tp.`receive_time`)) <= '2015-10-31'
GROUP BY tp.`bid_id`, DATE(tp.`receive_time`);
执行时间:
/* Affected rows: 0 已找到记录: 129 警告: 0 持续时间 1 query: 0.671 sec. */
结果一样,但最终结果只需0.67s
优化思路,原来语句explain中:
在select_type中有大量的dependent_subquery,此种类型的查询极耗性能,在sql的编写中应该极力避免。
- 结合业务需求,查看group by写法,发现没有必要写那么多的group by,只需要抓住核心的tp.`bid_id`, DATE(tp.`receive_time`)便可确定一组帐单信息。
2. 尽量改写查询列,让其为subquery,如下:
SELECT
YEAR(IFNULL(tp.`real_receive_time`, tp.`receive_time`)) AS `year`,
MONTH(IFNULL(tp.`real_receive_time`, tp.`receive_time`)) AS `month`,
tp.bid_id,
b.`title`,
DATE(b.`time`) `time`,
DATE(IFNULL(tp.`real_receive_time`, tp.`receive_time`)) AS `receive_date`,
u.`name`,
u.`reality_name`,
b.`amount`,
b.`apr`,
b.`period_unit`,
b.`period`,
sum(if(tp.real_receive_time,tp.`receive_interest`,0)) receive_interest,
COUNT(1) AS bid_invest_count ,
IFNULL((SELECT SUM(s.`amount`) FROM t_invests s WHERE s.`bid_id`=tp.bid_id and s.user_id IN (SELECT r.user_id FROM `t_user_repair` r)), 0) as bid_amount1,
sum(if(tp.user_id in (SELECT r.user_id FROM `t_user_repair` r) and tp.real_receive_time is not null,tp.receive_corpus,0 )) bid_corpus1,
sum(if(tp.user_id in (SELECT r.user_id FROM `t_user_repair` r) and tp.real_receive_time is not null,tp.receive_interest,0 )) bid_interest1,
sum(if(tp.user_id in (SELECT r.user_id FROM `t_user_repair` r),1,0 )) bid_invest_count1,
sum(if(tp.user_id not in (SELECT r.user_id FROM `t_user_repair` r) and tp.real_receive_time is not null,tp.receive_corpus,0 )) bid_corpus2
FROM t_bill_invests tp
LEFT JOIN t_bids b ON tp.bid_id=b.`id`
LEFT JOIN t_users u ON b.`user_id`=u.`id`
WHERE 1=1 AND DATE(IFNULL(tp.`real_receive_time`, tp.`receive_time`)) >= '2015-04-01' AND DATE(IFNULL(tp.`real_receive_time`, tp.`receive_time`)) <= '2015-10-31'
GROUP BY tp.`bid_id`, DATE(tp.`receive_time`);
在其explain中还有残留的依赖外查询:
主要是由框中的语句引起,于是再改写,让其改成临时表连接,就是最后的sql语句:
只剩临时表与了查询,性能有了大幅度的提升,优化结束。
总结:统计类查询经常不小心就会写成depended_subquery的形式,可以结合sum count case if条件判断来改写,让其可以达到subquery的形式,另一方面也可以改成临时表的方式并通过连接来提高性能。
mysql depended_query 优化案例一则的更多相关文章
- MySQL filesort优化案例一则
今天遇到一个filesort优化的案例,感觉不错,分享出来. MySQL中filesort是什么意思?官方手册定义: MySQL must do an extra pass to find out h ...
- MySQL参数优化案例
环境介绍 优化层级与指导思想 优化过程 最小化安装情况下的性能表现 优化innodb_buffer_pool_size 优化innodb_log_files_in_group&innodb_l ...
- MySQL索引优化案例
这里我们分成三种情况进行分析,分别是单表,两表,三表 1.单表 CREATE TABLE IF NOT EXISTS `article`( `id` ) NOT NULL PRIMARY KEY AU ...
- MySQL索引优化案例浅析
MySQL是关系型数据库的一种,查询功能强,数据一致性高,数据安全性高,支持二级索引.但是性能比起非关系型数据库稍弱,特别是百万级以上的数据,很容易出现查询慢的现象.这时候要分析慢的原因,一般情况下是 ...
- mysql优化案例
MySQL优化案例 Mysql5.1大表分区效率测试 Mysql5.1大表分区效率测试MySQL | add at 2009-03-27 12:29:31 by PConline | view:60, ...
- MySQL的索引单表优化案例分析
建表 建立本次优化案例中所需的数据库及数据表 CREATE DATABASE db0206; USE db0206; CREATE TABLE `db0206`.`article`( `id` INT ...
- 记一次mysql多表查询(left jion)优化案例
一次mysql多表查询(left jion)优化案例 在新上线的供需模块中,发现某一个查询按钮点击后,出不来结果,找到该按钮对应sql手动执行,发现需要20-30秒才能出结果,所以服务端程序判断超时, ...
- Mysql性能优化三(分表、增量备份、还原)
接上篇Mysql性能优化二 对表进行水平划分 如果一个表的记录数太多了,比如上千万条,而且需要经常检索,那么我们就有必要化整为零了.如果我拆成100个表,那么每个表只有10万条记录.当然这需要数据在逻 ...
- MySQL架构优化实战系列1:数据类型与索引调优全解析
一.数据类型优化 数据类型 整数 数字类型:整数和实数 tinyint(8).smallint(16).mediuint(24).int(32).bigint(64) 数字表示对应最大存储位数,如 ...
随机推荐
- iOS 7.1 UITableView添加footerView 后 最后一行分割线无法显示
今天用故事版 遇到个奇怪的问题: 我要用 tbView(tableView)展示写信息.最后一行我要显示些文案什么的.考虑用 footerView ,开心coding ..,show下 哪里有些不对吧 ...
- 微信中直接下载APK
某天在微信中偶遇一个二维码,识别二维码竟然可以直接下载APK! 该二维码如下: 解码后获得地址:(在线解码工具) http://www.rmdown.com/newt66y.apk 这不就是个普通的A ...
- Swift 3 新特性和迁移详解
写在前面 Swift 3.0 正式版发布了差不多快一个月了,断断续续的把手上和 Swift 相关的迁移到了Swift 3.0.所以写点小总结. 背景 代码量(4万行) 首先,我是今年年初才开始入手 S ...
- sudo 使用不了, the permissions on the /etc/sudoers file are changed to something other than 0440
sudo 使用不了,报错: the permissions on the /etc/sudoers file are changed to something other than 0440 how ...
- 在线PDF编辑网站http://www.pdfescape.com
网站地址:http://www.pdfescape.com 先转载一个简单介绍的文章 如果你以前很少阅读PDF文档,电脑中也没有PDF阅读器:adobe reader,foxit reader之类的软 ...
- java-cef系列视频第一集:从官方代码编译
本视频介绍了如何从官方给出步骤编译java-cef代码,生成可运行可移植的发行版. 值得一提的是:截至2016-09-24java-cef代码编译方式有所改变,读者请自行查看bitbucket上关于编 ...
- 康力优蓝机器人 -- 优友U05类人型机器人发布
[寒武计划]优友U05类人型机器人发布: http://digi.tech.qq.com/a/20151124/043234.htm?pgv_ref=aio2015&ptlang=2052 北 ...
- HTML5本地存储之localStorage、sessionStorage
1.概述 localStorage和sessionStorage统称为Web Storage,它使得网页可以在浏览器端储存数据. sessionStorage保存的数据用于浏览器的一次会话,当会话结束 ...
- 提高c++性能的编程技术笔记
需要时再创建对象,比如在类中用if new 而不是在构造函数里创建类的成员. 用char 指针而不是string可以节省构造和析构string的开销. 虚函数无法内联的性能损失.
- Qt编写自定义控件大全
最新版可执行文件 http://pan.baidu.com/s/1i491FQP 不定期增加控件及修正BUG和改进算法. 总图: 1:动画按钮 * 1:可设置显示的图像和底部的文字 * 2:可设置普通 ...