这是表格定义
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
表格有问题吗?
答案 0 :(得分:2)
我会说,这是因为你使用的是MyISAM引擎。
在我的Answer中可以看到它与INNODB的完美结合。
我会尽力在这个问题上起到至少一个光荣的参考。
这里,The range Join Type,显然是INNODB焦点,因为它是默认引擎。如果在某些文档层次结构的手册中没有明确提到,则会假定它。
注意,我的示例链接中的id没有任何连续性。意思是,不要在其EXPLAIN输出中对type=range
进行超聚焦。速度通过优化器(CBO)得出。
我的例子中的cardinality
非常高(4.3百万)。目标id计数相对较低(1000)。使用索引。
您的情况可能相反:您的基数可能非常低,如3,优化程序决定放弃使用索引。
要检查索引cardinality
,请参阅手册页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 | | |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
答案 1 :(得分:0)
当需要获取“太多”的表时,MyISAM和InnoDB都不可能使用索引。
IN (5,6)
可能意味着需要扫描表的2/12?或者数据可能存在偏差,以至于这两个月的行数超过它们的份额?
优化器可能在这种情况下避开索引的原因......
使用这样的索引时,需要花费大量时间在索引(一个BTree)和数据之间反弹。
当不使用索引时,它只是通过数据巡航,忽略行的10/12。 可能实际上更快。