MySQL有没有办法。如何加快查询速度

时间:2016-03-16 05:25:21

标签: mysql performance

我做了一个查询,它给了我需要的结果,但速度非常慢。

DB:Mysql

问题:非常慢。

问题:我有什么方法可以加快查询速度!

提前致谢!

SELECT  Count(*) AS totalCount
    FROM  
      ( SELECT  Max(issue_cnt) AS max_count, deal_id, issue_date, penalty_point,
                sale_volume, penalty_classify_code
            FROM  
              ( SELECT  penalty.deal_id, Count(*) AS issue_cnt,
                        Max(penalty_point) AS max_point,
                        penalty.issue_date, penalty.penalty_point,
                        penalty.sale_volume,
                        penalty.penalty_classify_code
                    FROM  bizinfo.tb_pc_sale_penalty penalty, 
                      ( SELECT  Max(penalty_point) AS max_point,
                                penalty.deal_id, penalty.issue_date,
                                penalty.sale_volume,
                                penalty.penalty_classify_code
                            FROM  bizinfo.tb_pc_sale_penalty penalty,
                                  bizinfo.tb_deal_info deal
                            WHERE  penalty.deal_id = deal.deal_id
                              AND  penalty.issue_date >= '2016-01-01'
                              AND  penalty.issue_date < '2016-03-16'
                              AND  Date_format(penalty.registe_date, '%Y-%m-%d') <=
                                   Date_format(Now(), '%Y-%m-%d')
                            GROUP BY  deal_id , issue_date
                      ) terms
                    WHERE  penalty.deal_id = terms.deal_id
                      AND  penalty.issue_date = terms.issue_date
                      AND  penalty.sale_volume = terms.sale_volume
                      AND  penalty.penalty_point = terms.max_point
                      AND  penalty.issue_date >= '2016-01-01'
                      AND  penalty.issue_date < '2016-03-16'
                      AND  Date_format(penalty.registe_date, '%Y-%m-%d') <=
                           Date_format(Now(), '%Y-%m-%d' )
                    GROUP BY  deal_id , penalty.sale_volume , issue_date ,
                              penalty.penalty_classify_code
              ) choice
            GROUP BY  deal_id , issue_date
      ) selection
    left join  
      ( SELECT  1 AS cnt, penalty_classify_code, penalty_point,
                process_condition,
                deal_id, issue_date, registe_date, company_id
            FROM  bizinfo.tb_pc_penalty_point_finalize
            WHERE  issue_date >= '2016-01-01'
              AND  issue_date < '2016-03-16'
      ) finalize ON selection.deal_id = finalize.deal_id
      AND  selection.issue_date = finalize.issue_date
    left join  
      ( SELECT  Ifnull(SUM(penalty_point), 0) AS point, company_id
            FROM  bizinfo.tb_pc_penalty_point_finalize
            WHERE  process_condition = 1
              AND  penalty_point > 0
              AND  registe_date >= Date_sub(Curdate(), interval 89 day)
              AND  registe_date < Date_format(Now(), '%Y-%m-%d')
            GROUP BY  company_id
      ) cumulate ON finalize.company_id = cumulate.company_id
    left join  
      ( SELECT  Count(*) AS cnt, penalty.deal_id, penalty.issue_date
            FROM  bizinfo.tb_pc_sale_penalty penalty, bizinfo.tb_deal_info deal
            WHERE  deal.deal_id = penalty.deal_id
              AND  penalty.issue_date >= '2016-01-01'
              AND  penalty.issue_date < '2016-03-16'
              AND  penalty_point < 0
            GROUP BY  deal_id , issue_date
      ) suspension ON selection.deal_id = suspension.deal_id
      AND  selection.issue_date = suspension.issue_date
    left join  
      ( SELECT  penalty.deal_id, penalty.issue_date, Count(*) AS all_issue_count,
                Ifnull(exp.explain_cnt, 0) AS explain_count,
                SUM(penalty.penalty_point) AS penalty_cumulative_point,
                penalty_point AS penalty_allocate_point, deal.company_id,
                deal.md_id, deal.team_id, deal.main_name
            FROM  
              ( SELECT  deal_id,
                        CASE WHEN penalty_point > 0
                             THEN penalty_point
                             ELSE 0 END AS penalty_point,
                        issue_date
                    FROM  bizinfo.tb_pc_sale_penalty
              ) penalty
            left join  
              ( SELECT  1 AS explain_cnt, exp.deal_id, exp.issue_date
                    FROM  bizinfo.tb_pc_penalty_explain exp
                    GROUP BY  exp.deal_id , exp.issue_date
              ) exp ON exp.deal_id = penalty.deal_id
              AND  exp.issue_date = penalty.issue_date, bizinfo.tb_deal_info deal
            WHERE  penalty.deal_id = deal.deal_id
            GROUP BY  penalty.deal_id , penalty.issue_date , deal.company_id
      ) alltype ON selection.deal_id = alltype.deal_id
      AND  selection.issue_date = alltype.issue_date, bizinfo.tb_deal_info deal,
        bizinfo.tb_partner_member member, bizinfo.tb_partner_member member2,
        bizinfo.tb_pc_communication_master_code master,
        bizinfo.tb_company_info company
    WHERE  selection.deal_id = deal.deal_id
      AND  deal.md_id = member.user_id
      AND  deal.team_id = member2.user_seq
      AND  master.group_cd = 'P10080'
      AND  master.value_cd NOT IN ('p99')
      AND  master.value_cd = selection.penalty_classify_code
      AND  alltype.company_id = company.company_id;

3 个答案:

答案 0 :(得分:1)

是的,您可以将索引应用于 WHERE 子句中使用的列 就像在selection.deal_id,deal.deal_id,deal.md_id和member.user_id上添加索引一样。 但是在桌子上有太多的索引并不好。

作为一般规则,您应该在所有主键上都有索引(您没有选择),所有外键以及您常用于获取行的任何其他字段。

答案 1 :(得分:1)

在查询中涉及的列上创建INDEX。

FLUSH TABLES

RESET QUERY CACHE
上面的

将释放一些内存空间。 祝你好运

答案 2 :(得分:1)

使用FROM a JOIN b ON ...语法代替FROM a,b WHERE ...

FROM ( SELECT ... ) JOIN ( SELECT ... ) ON ...(或较旧的格式)优化不佳。尽量避免它。

Date_format(Now(), '%Y-%m-%d') - &gt; CURRENT_DATE()

这更简单,更优化;我怀疑它给出了相同的意图&#39;:

Date_format(penalty.registe_date, '%Y-%m-%d') <=
Date_format(Now(), '%Y-%m-%d' )
-->
penalty.registe_date < NOW()

请提供SHOW CREATE TABLE,以便我们判断索引的效用并了解数据类型。 (示例:issue_date为DATE还是DATETIME?)请提供EXPLAIN SELECT,以便我们查看当前正在执行的查询。

考虑JOIN是否合适而不是LEFT JOIN

您运行的是哪个版本的MySQL?

penalty可能会受益于INDEX(deal_id, issue_date, sale_volume, penalty_point, registe_date) - 特别是registe_date最后一次。

在其中一个早期子查询中,为什么包含deal? (... FROM bizinfo.tb_pc_sale_penalty penalty, bizinfo.tb_deal_info deal ...)如果没有dealINDEX(deal_id, issue_date)将是一个非常好的索引。如果您加入deal,我不确定该推荐什么。

tb_pc_penalty_point_finalize需要INDEX(issue_date)

left join ( SELECT Ifnull(SUM(penalty_point), 0) AS point ...可以完全删除!这是额外的工作,但您不能使用它生成的point。而且,由于它是LEFT,没有人关心SELECT是否找到了什么。也许其他LEFT JOINs也没用?

master可能需要INDEX(group_cd); selection可能需要INDEX(penalty_classify_code)