月度利息统计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的编写中应该极力避免。

  1. 结合业务需求,查看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 优化案例一则的更多相关文章

  1. MySQL filesort优化案例一则

    今天遇到一个filesort优化的案例,感觉不错,分享出来. MySQL中filesort是什么意思?官方手册定义: MySQL must do an extra pass to find out h ...

  2. MySQL参数优化案例

    环境介绍 优化层级与指导思想 优化过程 最小化安装情况下的性能表现 优化innodb_buffer_pool_size 优化innodb_log_files_in_group&innodb_l ...

  3. MySQL索引优化案例

    这里我们分成三种情况进行分析,分别是单表,两表,三表 1.单表 CREATE TABLE IF NOT EXISTS `article`( `id` ) NOT NULL PRIMARY KEY AU ...

  4. MySQL索引优化案例浅析

    MySQL是关系型数据库的一种,查询功能强,数据一致性高,数据安全性高,支持二级索引.但是性能比起非关系型数据库稍弱,特别是百万级以上的数据,很容易出现查询慢的现象.这时候要分析慢的原因,一般情况下是 ...

  5. mysql优化案例

    MySQL优化案例 Mysql5.1大表分区效率测试 Mysql5.1大表分区效率测试MySQL | add at 2009-03-27 12:29:31 by PConline | view:60, ...

  6. MySQL的索引单表优化案例分析

    建表 建立本次优化案例中所需的数据库及数据表 CREATE DATABASE db0206; USE db0206; CREATE TABLE `db0206`.`article`( `id` INT ...

  7. 记一次mysql多表查询(left jion)优化案例

    一次mysql多表查询(left jion)优化案例 在新上线的供需模块中,发现某一个查询按钮点击后,出不来结果,找到该按钮对应sql手动执行,发现需要20-30秒才能出结果,所以服务端程序判断超时, ...

  8. Mysql性能优化三(分表、增量备份、还原)

    接上篇Mysql性能优化二 对表进行水平划分 如果一个表的记录数太多了,比如上千万条,而且需要经常检索,那么我们就有必要化整为零了.如果我拆成100个表,那么每个表只有10万条记录.当然这需要数据在逻 ...

  9. MySQL架构优化实战系列1:数据类型与索引调优全解析

    一.数据类型优化 数据类型 整数   数字类型:整数和实数 tinyint(8).smallint(16).mediuint(24).int(32).bigint(64) 数字表示对应最大存储位数,如 ...

随机推荐

  1. 1、Orchard商城开发——开发需求

    需要开发的功能: 1.商品详情,可添加商品属性,如颜色,尺寸等. 2.商品类别,可显示该类别下的所有商品,可按品牌.颜色.尺寸等检索,并可按价格.销量等排序游览. 3.商品游览记录,收藏商品,加入购物 ...

  2. LCLFramework框架之Service模式

    Service模式介绍 领域中的一些概念不太适合建模为对象,即归类到实体对象或值对象,因为它们本质上就是一些操作,一些动作,而不是事物.这些操作或动作往往会涉及到多个领域对象,并且需要协调这些领域对象 ...

  3. java模拟开锁

    java模拟开锁 service qq:928900200 Introduction to Computer Science II: CSCI142Fall 2014Lab #1Instructor: ...

  4. 【html】button按钮的一些问题

    问题: button 按钮在不设置 type 属性时,在不同的浏览器作用不一样.举个例子: html: <!doctype html> <html lang="en&quo ...

  5. [转]HTTP请求模型和头信息

    原文链接:http://www.java3z.com/cwbwebhome/article/article2/2406.html 目录 一.连接至Web服务器 二.发送HTTP请求 三.服务端接受请求 ...

  6. [AX 2012] Woker user request

    在HR模块和System administrator模块下都能找到Woker user request这个功能,它的作用是为员工创建一个AX账号.比如我们创建一个这样的user request: 注意 ...

  7. 记一次VNC远程连接Linux问题解决记录(5900端口测试、KDE桌面安装)

    最近几天,到一个项目上安装Linux部署环境.由于服务器在机房,而进机房又比较麻烦,于是选择VNC远程连接Linux就显得自然而然了.以前也用过VNC,而且还经常使用,由于各个项目环境不太一样,这次也 ...

  8. VC中使用ATL库实现正则表达式匹配(ADODB::Error)

    1. 确保项目属性中ATL使用处于打开状态. 如VS中项目属性常规—ATL使用—静态链接到ATL 2. 在使用时加上头文件 #include "atlrx.h" 3. 使用示例代码 ...

  9. caffe上使用hdf5格式文件以及回归(regression)问题

    最近用caffe做了一下regression问题,先用data layer中的data,float_data试了一下,data用来存放图片,float_data存放regression的values, ...

  10. 当应用程序不是以 UserInteractive 模式运行时显示模式对话框或窗体是无效操作

    在Web程序中引用了WinForm的类库引起了 主要是为了在web程序中使用Message.Show()以及SaveFileDialog类,能web程序中引用了WinForm类库 在Visual St ...