Bug #46475 Different optimizations chosen for exactly equivalent queries
Submitted: 30 Jul 2009 11:24 Modified: 31 Jul 2009 6:54
Reporter: Philip Stoev Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Optimizer Severity:S3 (Non-critical)
Version:5.1,5.4 OS:Any
Assigned to: CPU Architecture:Any

[30 Jul 2009 11:24] Philip Stoev
Description:
The queries above are completely equivalent and yet they produce different optimizations.

The more advanced intersect optimization is only picked if constant expression simplification takes place. Similar behavior was observed with BKA. This points to an underlying issue with the optimizer which may prevent a wide range of queries from benefitting from better optimizations.

mysql>   EXPLAIN  SELECT `datetime_key`  FROM C  WHERE  `pk`  <  128  AND `int_key`  BETWEEN  125  AND  (125  +  0)  \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: C
         type: index_merge
possible_keys: PRIMARY,int_key
          key: int_key,PRIMARY
      key_len: 5,4
          ref: NULL
         rows: 1
        Extra: Using intersect(int_key,PRIMARY); Using where
1 row in set (0.00 sec)

mysql>   EXPLAIN  SELECT `datetime_key`  FROM C  WHERE  `pk`  <  128  AND `int_key`  BETWEEN  125  AND  125 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: C
         type: ref
possible_keys: PRIMARY,int_key
          key: int_key
      key_len: 5
          ref: const
         rows: 1
        Extra: Using where
1 row in set (0.00 sec)

How to repeat:
SET SQL_MODE='NO_ENGINE_SUBSTITUTION';

CREATE TABLE `C` (
  `pk` int(11) NOT NULL AUTO_INCREMENT,
  `int_nokey` int(11) DEFAULT NULL,
  `int_key` int(11) DEFAULT NULL,
  `date_key` date DEFAULT NULL,
  `date_nokey` date DEFAULT NULL,
  `time_key` time DEFAULT NULL,
  `time_nokey` time DEFAULT NULL,
  `datetime_key` datetime DEFAULT NULL,
  `datetime_nokey` datetime DEFAULT NULL,
  `varchar_key` varchar(1) DEFAULT NULL,
  `varchar_nokey` varchar(1) DEFAULT NULL,
  PRIMARY KEY (`pk`),
  KEY `int_key` (`int_key`),
  KEY `date_key` (`date_key`),
  KEY `time_key` (`time_key`),
  KEY `datetime_key` (`datetime_key`),
  KEY `varchar_key` (`varchar_key`,`int_key`)
) ENGINE=InnoDB;

INSERT INTO `C` VALUES (1,NULL,7,'2005-12-13','2005-12-13','20:20:53','20:20:53',NULL,NULL,'l','l'),(2,5,0,'2003-01-01','2003-01-01','13:53:03','13:53:03','2003-09-12 02:19:51','2003-09-12 02:19:51','k','k'),(3,9,2,'2003-03-05','2003-03-05','12:37:08','12:37:08','2006-07-13 12:22:41','2006-07-13 12:22:41',NULL,NULL),(4,3,NULL,'2001-01-25','2001-01-25','00:00:00','00:00:00','0000-00-00 00:00:00','0000-00-00 00:00:00','u','u'),(5,134,122,'2003-03-17','2003-03-17','15:59:14','15:59:14','2000-10-03 15:17:43','2000-10-03 15:17:43','e','e'),(6,NULL,NULL,'2004-09-14','2004-09-14','04:43:51','04:43:51','2009-04-25 16:10:46','2009-04-25 16:10:46','v','v'),(7,1,1,NULL,NULL,'06:49:25','06:49:25','2005-01-11 03:31:23','2005-01-11 03:31:23','i','i'),(8,4,7,'2009-10-17','2009-10-17','15:25:21','15:25:21','2002-12-22 17:39:46','2002-12-22 17:39:46',NULL,NULL),(9,1,2,'2006-11-04','2006-11-04','18:16:04','18:16:04','2007-06-18 19:09:43','2007-06-18 19:09:43','u','u'),(10,0,7,'0000-00-00','0000-00-00','00:00:00','00:00:00','2001-06-14 20:33:16','2001-06-14 20:33:16','f','f'),(11,NULL,9,'2007-04-19','2007-04-19','18:36:41','18:36:41','2005-03-06 05:45:38','2005-03-06 05:45:38','u','u'),(12,8,6,'2003-08-18','2003-08-18','18:50:55','18:50:55','2000-10-01 17:07:48','2000-10-01 17:07:48','m','m'),(13,224,127,'2008-06-19','2008-06-19',NULL,NULL,'0000-00-00 00:00:00','0000-00-00 00:00:00','j','j'),(14,90,198,'0000-00-00','0000-00-00','08:22:36','08:22:36','2002-02-13 21:59:10','2002-02-13 21:59:10','f','f'),(15,NULL,217,'2004-01-02','2004-01-02',NULL,NULL,'2008-09-21 04:36:56','2008-09-21 04:36:56','v','v'),(16,2,6,'2007-08-12','2007-08-12','09:37:21','09:37:21',NULL,NULL,'j','j'),(17,6,4,'2009-02-28','2009-02-28','03:03:26','03:03:26','2007-04-18 12:09:11','2007-04-18 12:09:11','g','g'),(18,6,8,'2008-08-01','2008-08-01','23:43:45','23:43:45','2001-12-25 21:55:34','2001-12-25 21:55:34','p','p'),(19,160,213,'2002-05-11','2002-05-11','08:19:59','08:19:59','2008-12-21 20:51:04','2008-12-21 20:51:04','u','u'),(20,3,1,NULL,NULL,'15:32:13','15:32:13','2007-05-06 06:09:03','2007-05-06 06:09:03',NULL,NULL);

EXPLAIN  SELECT `datetime_key`  FROM C  WHERE  `pk`  <  128  AND `int_key`  BETWEEN  125  AND  (125  +  0)
EXPLAIN  SELECT `datetime_key`  FROM C  WHERE  `pk`  <  128  AND `int_key`  
BETWEEN  125  AND  (125);