0

使用http://sqlfiddle.com/#!2/572f9/2中的表结构,

  1. 为什么使用的索引只有 company_id 而没有使用创建的索引?

  2. 为什么在我的机器上,使用完全相同的表结构和查询,在 POSSIBLE_KEYS 列中只出现 company_id?MySQL 版本:5.5.24-0ubuntu0.12.04.1-log (Ubuntu)

4

2 回答 2

2

我很确定您遇到了 5.5 中存在并在 5.6 中修复的错误。当使用不同的排序规则时,不使用日期时间列上的索引utf8_general_ci。请参阅以下链接:http ://bugs.mysql.com/bug.php?id=68942和http://bugs.mysql.com/bug.php?id=64998

对于在最左侧具有日期时间值的组合索引也是如此。因此,一个可能的解决方案是创建一个不以日期时间开头的组合索引。请参阅下面的示例测试会话,使用上面的示例。

因此,在您的情况下,我会尝试按照 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)
于 2013-07-29T12:25:33.007 回答
1

MySQL 根据它保存在表中的统计信息来确定在运行时使用哪个索引。根据数据选择不同的查询计划是正常的。

对于这个查询,它必须使用相交索引合并,这不是很有效,并且它决定(正确与否)不这样做。

如果在(company_id,status,created). 这样,它将能够直接从索引中过滤结果。

我想不出为什么只有一个键会尽可能出现(假设你真的有两个键)。

于 2013-07-29T10:49:37.697 回答