【问题标题】:Mysql Performace issue with LEFT-JOIN and Group ByLEFT-JOIN 和 Group By 的 Mysql 性能问题
【发布时间】:2015-01-09 11:45:58
【问题描述】:

我有 2 个表 EMP 和 EMP_DTL。我正在使用 LEFT JOIN,如下所示。

SELECT EMPDEL, 
    EMPYEAR, 
    EXCODE, 
    CONCAT(COALESCE(TCODE, ''), COALESCE(INTCODE, '')) AS INTCODE, 
    (   SELECT GROUP_CONCAT(ECODE SEPARATOR ' ') FROM EMP_DTL 
        WHERE EMP_DTL.DTL_EID = EMP.EID AND ETYPE='')  AS ECODE, 
    COUNT(SSN)                                         AS SSN,
    MIN(ESRP)                                          AS ESRP, 
    GROUP_CONCAT(DISTINCT CURCODE SEPARATOR ' ')       AS CURCODE 
 FROM EMP 
 WHERE EAND='TOY' 
    AND EMPYEAR IN ('2014', '2015') 
    AND EGORY IN('G') 
    AND (EHIND = 'N' OR EHIND = 'FALSE') 
    AND EMP.SSN IS NOT NULL 
    AND ESRP > 0 
 GROUP BY EMPDEL, EMPYEAR, EXCODE, INTCODE, ECODE

而且表结构是这样的,

CREATE TABLE `emp` (
  `EID` varchar(45) NOT NULL,
  `ETYPE` varchar(1) NOT NULL,
  `SSN` varchar(20) DEFAULT NULL,
  `EMPDEL` varchar(4) DEFAULT NULL,
  `EMPYEAR` varchar(4) DEFAULT NULL,
  `ESCODE` varchar(2) DEFAULT NULL,
  `EIAL` varchar(45) DEFAULT NULL,
  `EAND` varchar(20) DEFAULT NULL,
  `ETUS` char(2) DEFAULT NULL,
  `ESRP` varchar(20) DEFAULT NULL,
  `EHIND` varchar(20) DEFAULT NULL,
  `EGORY` char(1) DEFAULT NULL,
  `ECODE` varchar(200) DEFAULT NULL,
  `EXCODE` varchar(10) DEFAULT NULL,
  `TCODE` varchar(5) DEFAULT NULL,
  `INTCODE` varchar(20) DEFAULT NULL,
  `CURCODE` varchar(10) DEFAULT NULL,
  `EAREA` varchar(5) DEFAULT NULL,
  PRIMARY KEY (`EID`),
  UNIQUE KEY `EID` (`EID`),
  KEY `SSN_IDX` (`SSN`),
  KEY `EMPDEL_IDX` (`EMPDEL`),
  KEY `EMPYEAR_IDX` (`EMPYEAR`),
  KEY `EAREA_IDX` (`EAREA`),
  KEY `ETUS_IDX` (`ETUS`),
  KEY `EAND_IDX` (`EAND`),
  KEY `ESRP_IDX` (`ESRP`),
  KEY `EHIND_IDX` (`EHIND`),
  KEY `EGORY_IDX` (`EGORY`)
) 

CREATE TABLE `emp_dtl` (
  `DTL_EID` varchar(45) NOT NULL,
  `SSN` varchar(20) DEFAULT NULL,
  `ECODE` varchar(45) NOT NULL,
  `ETYPE` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`DTL_EID`,`ECODE`),
  KEY `EMP_DTL_IDX` (`DTL_EID`),
  KEY `ETYPE_IDX` (`ETYPE`)
) 

问题是 Query 对 10000 条记录执行大约 30 秒。

我尝试在上述查询中添加这些内容以提高性能,

1) 添加“WHERE”子句

2) 在两个表上为 WHERE 子句中的 id 和列添加了适当的索引。

3) 执行执行计划以确保使用我的索引。这是执行计划的输出。

ID   SELECT_TYPE             TABLE      TYPE   POSSIBLE_KEYS                                                KEY                     KEY_LEN     REF      ROWS   EXTRA
=====================================================================================================================================================================================
'1', 'PRIMARY',             'EMP',     'ref', 'SSN_IDX,EMPYEAR_IDX,EAND_IDX,ESRP_IDX,EHIND_IDX, EGORY_IDX', 'EGORY_IDX',            '2',        'const', '13',  'Using where; Using filesort'
'2', 'DEPENDENT  SUBQUERY', 'EMP_DTL', 'ref', 'PRIMARY,EMP_DTL_IDX,ETYPE_IDX',                              'ETYPE_IDX',            '48',       'const', '1',   'Using where; Using index'

我应该再添加索引吗? 有人可以帮助我进一步优化此查询以减少执行时间吗?

【问题讨论】:

    标签: mysql performance optimization group-by left-join


    【解决方案1】:

    问题是您实际上并没有加入,而是在 EMP_DTL 中为 EMP 的每条记录单独查找。试试这个:

    SELECT EMP.EMPDEL, 
        EMP.EMPYEAR, 
        EMP.EXCODE, 
        CONCAT(COALESCE(TCODE, ''), COALESCE(INTCODE, '')) AS INTCODE, 
        GROUP_CONCAT(EMP_DTL.ECODE SEPARATOR ' ')          AS ECODE, 
        EMP.COUNT(SSN)                                     AS SSN,
        MIN(EMP.ESRP)                                      AS ESRP, 
        EMP.GROUP_CONCAT(DISTINCT CURCODE SEPARATOR ' ')   AS CURCODE 
     FROM EMP 
     LEFT JOIN EMP_DTL ON EMP_DTL.DTL_EID = EMP.EID AND EMP_DTL.ETYPE=''
     WHERE EAND='TOY' 
        AND EMPYEAR IN ('2014', '2015') 
        AND EGORY IN('G') 
        AND (EHIND = 'N' OR EHIND = 'FALSE') 
        AND EMP.SSN IS NOT NULL 
        AND ESRP > 0 
     GROUP BY EMPDEL, EMPYEAR, EXCODE, INTCODE, ECODE
    

    【讨论】:

      【解决方案2】:

      除了 Dirk 提供的左连接产品之外,您还可以在不同的字段上使用单独的索引,这些索引的帮助不如多键索引。尝试在您的表上放置一个索引以覆盖 WHERE 子句的主要元素和 group by 的元素...但是拥有这么多列可能太多而且不切实际。仅 WHERE 子句键上的结果集可能足以提高性能。

      在...上创建索引(EGORY、EAND、EMPYEAR、EHIND、SSN、ESRP)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-11
        • 2021-01-30
        相关资源
        最近更新 更多