mysql-IN子句不使用索引

这是表的定义

CREATE TABLE `dt_prdtime` (
  `TCompany` varchar(3) NOT NULL DEFAULT '',
  `TPerCode` varchar(8) NOT NULL,
  `TBegDateTime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'วันที่',
  `TQPay` int(1) NOT NULL DEFAULT '2',
  `TYear` int(4) NOT NULL,
  `TMonth` int(2) NOT NULL,
  PRIMARY KEY (`TCompany`,`TPerCode`,`TBegDateTime`),
  KEY `TMonth` (`TMonth`) USING BTREE,
  KEY `TPerCode` (`TPerCode`,`TYear`,`TMonth`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

这是数据样本.该表有10000条记录,并且TMonth字段中的值有所不同

+----------+----------+---------------------+-------+-------+--------+
| TCompany | TPerCode | TBegDateTime        | TQPay | TYear | TMonth |
+----------+----------+---------------------+-------+-------+--------+
| S10      | 000001   | 2016-01-02 17:33:00 |     1 |  2016 |      1 |
| S10      | 000001   | 2016-01-02 07:48:00 |     1 |  2016 |      1 |
| S10      | 000001   | 2016-01-03 17:39:00 |     1 |  2016 |      1 |
| S10      | 000001   | 2016-01-03 07:30:00 |     1 |  2016 |      1 |
| S10      | 000001   | 2016-01-04 17:49:00 |     1 |  2016 |      1 |
| S10      | 000001   | 2016-01-04 07:54:00 |     1 |  2016 |      1 |
| S10      | 000001   | 2016-01-05 17:50:00 |     1 |  2016 |      1 |
| S10      | 000001   | 2016-01-05 07:36:00 |     1 |  2016 |      1 |
| S10      | 000001   | 2016-01-06 17:37:00 |     1 |  2016 |      1 |
| S10      | 000001   | 2016-01-06 07:35:00 |     1 |  2016 |      1 |
+----------+----------+---------------------+-------+-------+--------+

通过EXPLAIN,此查询使用TMonth索引:

SELECT * FROM dt_prdtime WHERE TMonth = 5

而这个拒绝使用索引:

SELECT * FROM dt_prdtime WHERE TMonth IN (5,6)

我用另一个简单的表进行了测试,

CREATE TABLE `table1` (
  `id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

SELECT * FROM table2 WHERE id IN (5,6)

并且使用了该表的索引

有人可以解释吗? dt_prdtime表有问题吗?

解决方法:

我会弯腰说这是因为您使用的是MyISAM引擎.

正如我在这Answer中所看到的,它与INNODB完美配合.

我将尽力就此事至少引用1篇荣誉论文.

在这里,The range Join Type显然是INNODB的焦点,因为它是默认引擎.并且在手册中某些文档层次结构中未明确提及时,将采用此假设.

请注意,在我的示例链接中,id并不连续.意思是,不要过度关注其EXPLAIN输出中的type = range.速度是通过优化器(CBO)得出的.

在我的示例中,基数很高(430万).目标ID计数相对较低(1000).使用索引.

您的情况可能正好相反:您的基数可能非常低,例如3,优化器决定放弃使用索引.

要检查索引基数,请参见手册页SHOW INDEX Syntax.

一个简单的调用,例如:

show index from ratings;

+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table   | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| ratings |          0 | PRIMARY  |            1 | id          | A         |     4313544 |     NULL | NULL   |      | BTREE      |         |               |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
上一篇:使用索引获取项目,Python


下一篇:Mysql覆盖vs复合vs列索引