无法解释的慢速MySQL连接查询

时间:2014-07-07 10:41:27

标签: mysql sql

我有一个非常简单的查询,由于执行时间非常长而无法解释,因此令我感到头痛。查询:

explain select A.* from NAV_ADRESSEN A left outer join MITGL_KENNZEICHEN K on (K.MNR=A.MNR)
where ((A.MNR='19012546') or (IMPORTID='19012546') or (K.KENNZEICHEN='19012546')) and 
(not UNGUELTIG) order by ZUNAME, VORNAME limit 0, 25;

查询(真实的,而不是explain)大约需要17秒,无论是否找到任何匹配。

解释结果:

id  select_type table   type    possible_keys   key     key_len ref             rows Extra
1   SIMPLE      A       index   MNR,IMPORTID    ZUNAME  164     NULL            25   Using where
1   SIMPLE      K       ref     MNR             MNR     23      gsco-test.A.MNR 1    Using where

这看起来很正常。所有相关列都有密钥(A.MNR,K.MNR,A.IMPORTID,K.KENNZEICHEN);这些表包含~600 000行(NAV_ADRESSEN)和180行(MITGL_KENNZEICHEN)。

可能是什么问题?

已编辑添加:

当省略limit子句时(但执行时间加倍),解释看起来略有不同:

id  select_type  table  type  possible_keys  key   key_len  ref              rows    Extra                        
1   SIMPLE       A      ALL   MNR,IMPORTID   NULL  NULL     NULL             544587  Using where; Using filesort  
1   SIMPLE       K      ref   MNR            MNR   23       gsco-test.A.MNR  1       Using where                  

表格定义:

CREATE TABLE `MITGL_KENNZEICHEN` (
  `PK` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `MNR` varchar(20) DEFAULT NULL,
  `KENNZEICHEN` varchar(80) DEFAULT NULL,
  `DESCRIPTION` varchar(80) DEFAULT NULL,
  PRIMARY KEY (`PK`),
  KEY `MNR` (`MNR`),
  KEY `KENNZEICHEN` (`KENNZEICHEN`)
) ENGINE=InnoDB AUTO_INCREMENT=247 DEFAULT CHARSET=latin1;

......和......

CREATE TABLE `NAV_ADRESSEN` (
  `PK` int(11) NOT NULL AUTO_INCREMENT,
  `MNR` varchar(20) NOT NULL,
-- ... 50 fields omitted for brevity ...
  `UNGUELTIG` tinyint(1) NOT NULL,
  `IMPORTID` varchar(20) NOT NULL,
  `MATCHCODE` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`PK`),
  UNIQUE KEY `MNR` (`MNR`),
  KEY `ZUNAME` (`ZUNAME`,`VORNAME`),
  KEY `IMPORTID` (`IMPORTID`),
  KEY `MATCHCODE` (`MATCHCODE`),
  KEY `ANGELEGTDAT` (`ANGELEGTDAT`)
) ENGINE=InnoDB AUTO_INCREMENT=1076829 DEFAULT CHARSET=latin1;

1 个答案:

答案 0 :(得分:2)

仅供参考,该查询可以(可能)重写如下:

SELECT a.* 
  FROM nav_adressen a
  JOIN mitgl_kennzeichen k
    ON k.mnr = a.mnr
   AND 19012546 IN (a.mnr,importid,k.kennzeichen)
   AND NOT ungueltid 
 ORDER 
    BY zuname
     , vorname 
 LIMIT 0,25;