使用表格结构,如http://sqlfiddle.com/#!2/572f9/2,
为什么使用的索引只是company_id而且没有使用创建的索引?
为什么在我的机器上,使用完全相同的表结构和查询,在POSSIBLE_KEYS列中只显示company_id? MySQL版本:5.5.24-0ubuntu0.12.04.1-log(Ubuntu)
答案 0 :(得分:2)
我很确定你运行的是一个在5.5中出现并用5.6修复的bug。当使用与utf8_general_ci
不同的归类时,不使用datetime colums上的索引。请参阅以下链接:http://bugs.mysql.com/bug.php?id=68942和http://bugs.mysql.com/bug.php?id=64998。
对于在最左边部分具有日期时间值的组合索引也是如此。因此,一种可能的解决方案是创建一个不以datetime开头的组合索引。请参阅下面的示例测试会话,使用上面的示例。
因此,在您的情况下,我会尝试使用Vatev建议的组合索引,但请记住不要使用datetime列启动它。如果使用此索引,则取决于优化程序。但它将被列为可能的关键。一个不同的解决方案是使用5.1.xx或5.6(只有机会验证5.6.12,但错误报告指出它不会发生在5.1.60)。
mysql> SHOW VARIABLES LIKE "version";
+---------------+------------+
| Variable_name | Value |
+---------------+------------+
| version | 5.5.28-log |
+---------------+------------+
1 row in set (0.00 sec)
mysql> show variables like '%collation%';
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | utf8_general_ci |
| collation_database | latin1_swedish_ci |
| collation_server | latin1_swedish_ci |
+----------------------+-------------------+
3 rows in set (0.00 sec)
mysql> CREATE TABLE tbl (
-> id int(11) not null auto_increment PRIMARY KEY,
-> user_id int(11) not null,
-> company_id int (11) NOT NULL,
-> created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-> oid int(11) NOT NULL,
-> did varchar(100) NOT NULL,
-> status int(11) NOT NULL,
-> KEY company_id (company_id),
-> KEY user_id (user_id),
-> KEY created (created),
-> KEY operator_id (oid),
-> KEY did (did)
-> );
Query OK, 0 rows affected (0.01 sec)
mysql> EXPLAIN SELECT DATE_FORMAT(created, '%M %d, %Y') as date, count(id) as num_accepted FROM tbl WHERE created BETWEEN '2013-06-29' AND '2013-07-30' AND company_id = 20 AND (status in (2,5)) GROUP BY `date` ORDER BY created ASC;
+----+-------------+-------+------+--------------------+------------+---------+-------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+--------------------+------------+---------+-------+------+----------------------------------------------+
| 1 | SIMPLE | tbl | ref | company_id,created | company_id | 4 | const | 1 | Using where; Using temporary; Using filesort |
+----+-------------+-------+------+--------------------+------------+---------+-------+------+----------------------------------------------+
1 row in set (0.00 sec)
mysql> SET collation_connection = utf8_unicode_ci;
Query OK, 0 rows affected (0.00 sec)
mysql> EXPLAIN SELECT DATE_FORMAT(created, '%M %d, %Y') as date, count(id) as num_accepted FROM tbl WHERE created BETWEEN '2013-06-29' AND '2013-07-30' AND company_id = 20 AND (status in (2,5)) GROUP BY `date` ORDER BY created ASC;
+----+-------------+-------+------+---------------+------------+---------+-------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------------+---------+-------+------+----------------------------------------------+
| 1 | SIMPLE | tbl | ref | company_id | company_id | 4 | const | 1 | Using where; Using temporary; Using filesort |
+----+-------------+-------+------+---------------+------------+---------+-------+------+----------------------------------------------+
1 row in set (0.00 sec)
答案 1 :(得分:1)
MySQL确定在运行时使用哪个索引,具体取决于它在表上保留的统计信息。根据数据选择不同的查询计划是正常的。
对于此查询,它必须使用交叉索引合并,这不是非常有效,并且它决定(正确与否)不执行此操作。
如果在(company_id,status,created)
上创建索引会好得多。这样它就可以直接从索引中过滤结果。
我想不出为什么只有一个键出现的原因(假设你真的有两个键)。