我有一个下面的查询,它使用索引,但还没有优化,我不知道是什么问题,有人能帮我吗?

select 
  date(mfd.MFD_FITMENT_DATE) as MFD_FITMENT_DATE, 
  count(*) cnt_fitment 
FROM 
  MMHSRP_FITMENT_DATE mfd, 
  CUSTOMER_REGISTRATION_DETAILS crd, 
  EMBOSSING_STATION_MAPPING_DETAILS esmd 
where 
  mfd.MFD_CRD_ID = crd.CRD_ID 
  AND esmd.ESMD_SDM_ID = crd.CRD_SDM_ID 
  AND esmd.ESMD_ESM_ID = '9'
  AND mfd.MFD_STATUS = '0' 
  AND mfd.MFD_FITMENT_DATE >= '2022-10-07' 
  AND mfd.MFD_FITMENT_DATE <= '2022-12-06' 
  AND crd.CRD_VARIFICATION_STATUS IN (1, 2, 4) 
GROUP BY 
  mfd.MFD_FITMENT_DATE 
HAVING 
  COUNT(*) >= '5000' \G

    *************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: esmd
         type: ref
possible_keys: idx_ESMD_SDM_ID,idx_ESMD_ESM_ID
          key: idx_ESMD_ESM_ID
      key_len: 8
          ref: const
         rows: 440
        Extra: Using index condition; Using temporary; Using filesort
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: crd
         type: ref
possible_keys: PRIMARY,idx_CRD_SDM_ID,idx_CRD_VARIFICATION_STATUS,idx_crd_sdm_id_verfication_status
          key: idx_crd_sdm_id_verfication_status
      key_len: 4
          ref: celexkeyline.esmd.ESMD_SDM_ID
         rows: 660
        Extra: Using where; Using index
*************************** 3. row ***************************
           id: 1
  select_type: SIMPLE
        table: mfd
         type: ref
possible_keys: MFD_STATUS,idx_MFD_CRD_ID,idx_combo,idx_new,MFD_FITMENT_DATE,idx_CRD_FIT_DATE_STATUS
          key: MFD_STATUS
      key_len: 12
          ref: const,celexkeyline.crd.CRD_ID
         rows: 1
        Extra: Using where; Using index

第3行表格制造商 我使用了IDX_CRD_FIT_DATE_STATUS的力索引,但花费的时间仍然是相同的结果.

表 struct ;

第一行:

PRIMARY KEY (`ESMD_ID`),
  KEY `idx_ESMD_SDM_ID` (`ESMD_SDM_ID`),
  KEY `idx_ESMD_ESM_ID` (`ESMD_ESM_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=14006 DEFAULT CHARSET=latin1

第二行:

 PRIMARY KEY (`CRD_ID`),
  KEY `CRD_APP_ID` (`CRD_APP_ID`),
  KEY `idx_CRD_CMM_ID` (`CRD_CMM_ID`),
  KEY `idx_CRD_SDM_ID` (`CRD_SDM_ID`),
  KEY `idx_CRD_ZM_ID` (`CRD_ZM_ID`),
  KEY `idx_CRD_REGN_NUMBER` (`CRD_REGN_NUMBER`),
  KEY `idx_CRD_MOBILE_NUMBER` (`CRD_MOBILE_NUMBER`),
  KEY `idx_CRD_VARIFICATION_STATUS` (`CRD_VARIFICATION_STATUS`),
  KEY `idx_CRD_CHASSIS_NO` (`CRD_CHASSIS_NO`),
  KEY `idx_CRD_REGN_NUMBER_CRD_ID` (`CRD_REGN_NUMBER`,`CRD_ID`),
  KEY `CRD_FITMENT_DATE` (`CRD_FITMENT_DATE`),
  KEY `idx_crd_sdm_id_verfication_status` (`CRD_SDM_ID`,`CRD_VARIFICATION_STATUS`),
  KEY `idx_CRD_IS_REPLACEMENT` (`CRD_IS_REPLACEMENT`)

第三行:

 PRIMARY KEY (`MFD_ID`),
  KEY `MFD_STATUS` (`MFD_STATUS`,`MFD_CRD_ID`,`MFD_FITMENT_DATE`),
  KEY `idx_MFD_CRD_ID` (`MFD_CRD_ID`),
  KEY `idx_combo` (`MFD_FITMENT_DATE`,`MFD_CRD_ID`,`MFD_STATUS`),
  KEY `idx_new` (`MFD_STATUS`,`MFD_FITMENT_DATE`,`MFD_CRD_ID`),
  KEY `MFD_FITMENT_DATE` (`MFD_FITMENT_DATE`),
  KEY `idx_CRD_FIT_DATE_STATUS` (`MFD_CRD_ID`,`MFD_FITMENT_DATE`,`MFD_STATUS`)
) ENGINE=InnoDB AUTO_INCREMENT=2421779 DEFAULT CHARSET=latin1

上述索引均基于基数

Njdnsfkknkknknknknknknknknknknknkbnknknknkndsfkndnkndnkndsfndnknknknknkndfnknkndfntkndfndfntfnt.

推荐答案

您需要停止使用"老式联接".这种风格已经30多年没有流行了,正在阻碍你的脚步.如果我重写您的查询以使用现代连接,则如下所示:

SELECT  
  date(mfd.MFD_FITMENT_DATE) as MFD_FITMENT_DATE, 
  count(*) cnt_fitment 
FROM MMHSRP_FITMENT_DATE mfd
JOIN CUSTOMER_REGISTRATION_DETAILS crd ON mfd.MFD_CRD_ID = crd.CRD_ID
JOIN EMBOSSING_STATION_MAPPING_DETAILS esmd ON esmd.ESMD_SDM_ID = crd.CRD_SDM_ID 
WHERE 
      esmd.ESMD_ESM_ID = '9'
  AND mfd.MFD_STATUS = '0' 
  AND mfd.MFD_FITMENT_DATE >= '2022-10-07' 
  AND mfd.MFD_FITMENT_DATE <= '2022-12-06' 
  AND crd.CRD_VARIFICATION_STATUS IN (1, 2, 4) 
GROUP BY mfd.MFD_FITMENT_DATE 
HAVING COUNT(*) >= '5000' 

现在,我们可以看到两个筛选器位于链接表上--我们可以将这些筛选器移动到联接语句(这是使用旧式联接不能做的事情),如下所示:

SELECT  
  date(mfd.MFD_FITMENT_DATE) as MFD_FITMENT_DATE, 
  count(*) cnt_fitment 
FROM MMHSRP_FITMENT_DATE mfd
JOIN CUSTOMER_REGISTRATION_DETAILS crd ON mfd.MFD_CRD_ID = crd.CRD_ID
                                      AND crd.CRD_VARIFICATION_STATUS IN (1, 2, 4) 
JOIN EMBOSSING_STATION_MAPPING_DETAILS esmd ON esmd.ESMD_SDM_ID = crd.CRD_SDM_ID 
                                           and esmd.ESMD_ESM_ID = '9'
WHERE mfd.MFD_STATUS = '0' 
  AND mfd.MFD_FITMENT_DATE >= '2022-10-07' 
  AND mfd.MFD_FITMENT_DATE <= '2022-12-06' 
GROUP BY mfd.MFD_FITMENT_DATE 
HAVING COUNT(*) >= '5000' 

这应该会更快.

更多关于Stackoverflow自己的Arron Bernard https://sqlblog.org/2009/10/08/bad-habits-to-kick-using-old-style-joins的老式连接的讨论


备注中的子查询版本:

SELECT  
  date(mfd.MFD_FITMENT_DATE) as MFD_FITMENT_DATE, 
  count(*) cnt_fitment 
FROM (
   SELECT MFD_FITMENT_DATE, MFD_CRD_ID, MFD_STATUS 
   FROM MMHSRP_FITMENT_DATE mfd
   WHERE mfd.MFD_FITMENT_DATE >= '2022-10-07' 
     AND mfd.MFD_FITMENT_DATE <= '2022-12-06' 
) AS mfd 
JOIN CUSTOMER_REGISTRATION_DETAILS crd ON mfd.MFD_CRD_ID = crd.CRD_ID
                                      AND crd.CRD_VARIFICATION_STATUS IN (1, 2, 4) 
JOIN EMBOSSING_STATION_MAPPING_DETAILS esmd ON esmd.ESMD_SDM_ID = crd.CRD_SDM_ID 
                                           and esmd.ESMD_ESM_ID = '9'
WHERE mfd.MFD_STATUS = '0' 
GROUP BY mfd.MFD_FITMENT_DATE 
HAVING COUNT(*) >= '5000' 

Mysql相关问答推荐

使用JSON_CONTAINS搜索多个值的原理

基于多行从表中 Select

为什么 MAX 函数通过调用在 group 中生成正确的结果

避免多个SQL查询的重构代码

根据名称将值从一个字段复制到不同记录的同一字段

是否可以使用以EXPLAIN EXTENDED ...开头的 SQL 语句修改数据?

如何编写按天数汇总值的sql查询?

为生日创建 MySQL 索引

组平SQL查询结果

如何创建将行转换为列的 MySQL 查询?

创建表时我的 SQL 语句有什么问题

MySQL 1292 截断不正确的日期时间值:'2020-09-11T08:32-50Z'

MySQL 8 - MBRContains 不使用空间索引

如何使用 SQL 数据库中的经纬度查找最近的位置?

PHP MySQLI 防止 SQL 注入

MySQL中的行值增加和减少1

MySQL使用phpmyadmin重新排列列的顺序

如何使用 XML_LOAD() 将 XML 文件导入 MySQL 数据库表;功能

加快 mysql 转储和导入

带有 OuterRef 的简单子查询