MySQL选择不使用索引

时间:2016-12-05 11:30:33

标签: mysql sql indexing database-performance query-performance

我有一张表clicks

CREATE TABLE `clicks` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `link_id` int(11) NOT NULL,
  `date_added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
  PRIMARY KEY (`id`),
  KEY `link_id` (`link_id`),
  KEY `date_added` (`date_added`)
) ENGINE=InnoDB AUTO_INCREMENT=90899051 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

使用以下索引:

+--------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table  | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| clicks |          0 | PRIMARY    |            1 | id          | A         |    79808649 |     NULL | NULL   |      | BTREE      |         |               |
| clicks |          1 | link_id    |            1 | link_id     | A         |      276154 |     NULL | NULL   |      | BTREE      |         |               |
| clicks |          1 | date_added |            1 | date_added  | A         |    79808649 |     NULL | NULL   |      | BTREE      |         |               |
+--------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

我试图在这张桌子上运行一些分析性查询,而且我发现它需要花费很长时间才能运行。以下面的查询为例:

SELECT
    DISTINCT(link_id) AS link_id
FROM
    clicks
WHERE
    date_added >= '2016-11-01 00:00:00'
AND date_added <= '2016-12-05 10:16:00'

这个查询花了差不多一分钟才完成。我通过在查询上运行EXPLAIN找到索引未被使用。

+----+-------------+--------+-------+---------------+---------+---------+------+----------+-------------+
| id | select_type | table  | type  | possible_keys | key     | key_len | ref  | rows     | Extra       |
+----+-------------+--------+-------+---------------+---------+---------+------+----------+-------------+
|  1 | SIMPLE      | clicks | index | date_added    | link_id | 4       | NULL | 79786609 | Using where |
+----+-------------+--------+-------+---------------+---------+---------+------+----------+-------------+

我希望通过使用date_added列上的索引来过滤结果集,然后从结果中提取不同的link_id,就可以运行查询。

有谁知道为什么索引没有被使用,或者我有什么办法可以强迫它被使用?

注意:此问题是更大问题的一部分,与我上周发布的未解决问题密切相关 - MySQL query with JOIN not using INDEX

修改

在不使用任何索引提示的情况下解释我的查询:

EXPLAIN SELECT DISTINCT(link_id) FROM clicks WHERE date_added >= '2016-11-01 00:00:00' AND date_added <= '2016-12-05 23:59:59';
+----+-------------+---------------------------+-------+---------------+---------+---------+------+----------+-------------+
| id | select_type | table                     | type  | possible_keys | key     | key_len | ref  | rows     | Extra       |
+----+-------------+---------------------------+-------+---------------+---------+---------+------+----------+-------------+
|  1 | SIMPLE      | clicks                    | index | date_added    | link_id | 4       | NULL | 79816660 | Using where |
+----+-------------+---------------------------+-------+---------------+---------+---------+------+----------+-------------+

解释我的查询WITH索引提示:

EXPLAIN SELECT DISTINCT(link_id) FROM clicks USE INDEX(date_added) IGNORE INDEX(link_id) WHERE date_added >= '2016-11-01 00:00:00' AND date_added <= '2016-12-05 23:59:59';
+----+-------------+---------------------------+------+---------------+------+---------+------+----------+------------------------------+
| id | select_type | table                     | type | possible_keys | key  | key_len | ref  | rows     | Extra                        |
+----+-------------+---------------------------+------+---------------+------+---------+------+----------+------------------------------+
|  1 | SIMPLE      | clicks                    | ALL  | date_added    | NULL | NULL    | NULL | 79816882 | Using where; Using temporary |
+----+-------------+---------------------------+------+---------------+------+---------+------+----------+------------------------------+

修改2

在我的查询中使用FORCE INDEX(date_added)(查询更快完成,12.05秒):

EXPLAIN SELECT DISTINCT(link_id) FROM clicks FORCE INDEX(date_added) WHERE date_added >= '2016-11-01 00:00:00' AND date_added <= '2016-12-05 23:59:59';
+----+-------------+---------------------------+-------+---------------+------------+---------+------+----------+------------------------------+
| id | select_type | table                     | type  | possible_keys | key        | key_len | ref  | rows     | Extra                        |
+----+-------------+---------------------------+-------+---------------+------------+---------+------+----------+------------------------------+
|  1 | SIMPLE      | clicks                    | range | date_added    | date_added | 4       | NULL | 17277508 | Using where; Using temporary |
+----+-------------+---------------------------+-------+---------------+------------+---------+------+----------+------------------------------+

0 个答案:

没有答案