请考虑以下架构
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 |
+----+-------------+----------+------+---------------------+---------------------+---------+-------------+-------+--------------------------+
据我所知,需要额外的磁盘搜索。为什么不只是使用索引?
答案 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子句的所有查询都将显示“使用位置”。有时“使用位置”的存在暗示查询可以从不同的索引中受益。