MYSQL - 如何为/ group添加索引/ order by / sum / with where

时间:2016-05-10 07:01:18

标签: mysql optimization indexing

我正在处理一个40K行的mysql表。表indexed.c当前执行时间大约为2秒。有人指导我如何更好地优化此查询和表格?以及如何在...中使用;使用临时;使用filesort" ??。任何帮助表示赞赏。

与以下情况一起使用...

  1. LS_CHG_DTE_OCR
  2. LS_CHG_DTE_OCR / RES_STATE_HSE
  3. LS_CHG_DTE_OCR / RES_STATE_HSE / RES_CITY_HSE
  4. LS_CHG_DTE_OCR / RES_STATE_HSE / RES_CITY_HSE / POSTAL_CDE_HSE
  5. 提前致谢

    SELECT DATE_FORMAT(`LS_CHG_DTE_OCR`, '%Y-%b') AS fmt_date, 
        SUM(IF(`TYPE`='Connect',COUNT_SUBS,0)) AS connects, 
        SUM(IF(`TYPE`='Disconnect',COUNT_SUBS,0)) AS disconnects,
        SUM(IF(`TYPE`='Connect',ROUND(REV,2),0)) AS REV, 
        SUM(IF(`TYPE`='Upgrade',COUNT_SUBS,0)) AS upgrades, 
        SUM(IF(`TYPE`='Downgrade',COUNT_SUBS,0)) AS downgrades,
        SUM(IF(`TYPE`='Upgrade',ROUND(REV,2),0)) AS upgradeRev FROM `hsd`
        WHERE LS_CHG_DTE_OCR!='' GROUP BY MONTH(LS_CHG_DTE_OCR) ORDER BY LS_CHG_DTE_OCR ASC
    
    
    
    CREATE TABLE `hsd` (
      `id` int(10) NOT NULL AUTO_INCREMENT,
      `SYS_OCR` varchar(255) DEFAULT NULL,
      `PRIN_OCR` varchar(255) DEFAULT NULL,
      `SERV_CDE_OHI` varchar(255) DEFAULT NULL,
      `DSC_CDE_OHI` varchar(255) DEFAULT NULL,
      `LS_CHG_DTE_OCR` datetime DEFAULT NULL,
      `SALESREP_OCR` varchar(255) DEFAULT NULL,
      `CHANNEL` varchar(255) DEFAULT NULL,
      `CUST_TYPE` varchar(255) DEFAULT NULL,
      `LINE_BUS` varchar(255) DEFAULT NULL,
      `ADDR1_HSE` varchar(255) DEFAULT NULL,
      `RES_CITY_HSE` varchar(255) DEFAULT NULL,
      `RES_STATE_HSE` varchar(255) DEFAULT NULL,
      `POSTAL_CDE_HSE` varchar(255) DEFAULT NULL,
      `ZIP` varchar(100) DEFAULT NULL,
      `COUNT_SUBS` double DEFAULT NULL,
      `REV` double DEFAULT NULL,
      `TYPE` varchar(255) DEFAULT NULL,
      `lat` varchar(100) DEFAULT NULL,
      `long` varchar(100) DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `idx` (`LS_CHG_DTE_OCR`,`CHANNEL`,`CUST_TYPE`,`LINE_BUS`,`RES_CITY_HSE`,`RES_STATE_HSE`,`POSTAL_CDE_HSE`,`ZIP`,`COUNT_SUBS`,`TYPE`)
    ) ENGINE=InnoDB AUTO_INCREMENT=402342 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
    
    
    Using where; Using temporary; Using filesort[enter image description here][1]
    

2 个答案:

答案 0 :(得分:0)

您申请的唯一条件是LS_CHG_DTE_OCR!=“”。除此之外,由于聚合,您正在进行全表扫描。索引方面,你在这里做不了多少。

我遇到了同样的问题。我已经完全优化了我的查询(我有连接和更多条件)但是表不断增长并且查询时间也是如此。最后,我决定将数据镜像到ElasticSearch。在我的情况下,它将查询时间减少到大约1/20到1/100(对于不同的查询)。

答案 1 :(得分:0)

SELECT唯一可能的索引是INDEX(LS_CHG_DTE_OCR)。但它不太可能被使用。

  1. 执行WHERE - 如果有''个值的批次,则可以使用索引 进行过滤。
  2. GROUP BY MONTH(...) - 您可能会在同一个月内折叠多年。优化程序无法说明,因此它会使用索引。
  3. ORDER BY LS_CHG_DTE_OCR - 这是在 GROUP BY之后完成的。在收集数据之前无法执行ORDER BY - 对于任何索引来说都太迟了。但是,如果将多年折叠在一起,您可能会得到一些奇怪的结果。通过使ORDER BYGROUP BY相同来解决此问题。这也可以防止由GROUP BYORDER BY造成的额外排序。
  4. 是的,如果您添加的idx all SELECT中的列,那么它就是"覆盖索引"。但由于上述评论,它不会给任何人带来帮助。 "使用索引"不是很有帮助。

    GROUP BY LS_CHG_DTE_OCR/RES_STATE_HSE - 呃?将DATETIME除以VARCHAR?这听起来像是一场灾难。

    随着时间的推移,这张桌子会变得更大,对吗?考虑使用month构建和维护摘要表作为PRIMARY KEY

    的一部分