使用Index满足MySQL条件

时间:2011-11-17 00:54:40

标签: mysql indexing

请考虑以下架构

CREATE table articles (
    id Int UNSIGNED NOT NULL AUTO_INCREMENT,
    cat_id Int UNSIGNED NOT NULL,
    status Int UNSIGNED  NOT NULL,
    date_added Datetime,
    Primary Key (id)) ENGINE = InnoDB;

CREATE INDEX cat_list_INX ON articles (cat_id, status, date_added);
CREATE INDEX categories_list_INX ON articles (cat_id, status);

我已经写了两个查询,上述两个指标可以完全满足,但MySQL正在放在额外的列中。

mysql> EXPLAIN SELECT cat_id FROM articles USE INDEX (cat_list_INX) WHERE cat_id=158 AND status=2 ORDER BY date_added DESC LIMIT 500, 5;
+----+-------------+----------+------+---------------+--------------+---------+-------------+-------+--------------------------+
| id | select_type | table  ref         |   | type | possible_keys | key          | key_len | rows  | Extra                    |
+----+-------------+----------+------+---------------+--------------+---------+-------------+-------+--------------------------+
|  1 | SIMPLE      | articles | ref  | cat_list_INX  | cat_list_INX | 5       | const,const | 50698 | Using where; Using index |
+----+-------------+----------+------+---------------+--------------+---------+-------------+-------+--------------------------+


mysql> EXPLAIN SELECT cat_id FROM articles USE INDEX (categories_list_INX) WHERE cat_id=158 AND status=2;
+----+-------------+----------+------+---------------------+---------------------+---------+-------------+-------+--------------------------+
| id | select_type | tab key                 |le    | type | possible_keys       | key_len | ref         | rows  | Extra                    |
+----+-------------+----------+------+---------------------+---------------------+---------+-------------+-------+--------------------------+
|  1 | SIMPLE      | articles | ref  | categories_list_INX | categories_list_INX | 5       | const,const | 52710 | Using where; Using index |
+----+-------------+----------+------+---------------------+---------------------+---------+-------------+-------+--------------------------+

据我所知,需要额外的磁盘搜索。为什么不只是使用索引?

1 个答案:

答案 0 :(得分:4)

第一个查询是在存储引擎之外的mysql级别过滤记录,因为你的“ORDER BY”子句使用date_added字段。

这可以通过首先在索引中移动date_added字段来缓解,就像这个

一样
CREATE INDEX cat_list_INX ON articles (date_added, cat_id, status);

第二个查询 - 我的mysql版本没有显示“使用位置” - 我不希望这样 - 也许是因为我没有记录。

mysql> EXPLAIN SELECT cat_id FROM articles USE INDEX (categories_list_INX) WHERE cat_id=158 AND status=2;
+----+-------------+----------+------+---------------------+---------------------+---------+-------------+------+-------------+
| id | select_type | table    | type | possible_keys       | key                 | key_len | ref         | rows | Extra       |
+----+-------------+----------+------+---------------------+---------------------+---------+-------------+------+-------------+
|  1 | SIMPLE      | articles | ref  | categories_list_INX | categories_list_INX | 8       | const,const |    1 | Using index |
+----+-------------+----------+------+---------------------+---------------------+---------+-------------+------+-------------+
1 row in set (0.00 sec)

来自High Performance MySQL的额外列信息:

使用索引:这表明MySQL将使用覆盖索引来避免访问该表。不要将覆盖索引与索引访问类型混淆。

使用Where:这意味着MySQL服务器将在存储引擎检索后对行进行后置过滤。当(并且如果)它读取索引时,存储引擎可以检查涉及索引中的列的许多WHERE条件,因此并非具有WHERE子句的所有查询都将显示“使用位置”。有时“使用位置”的存在暗示查询可以从不同的索引中受益。