mysql索引优化1

mysql 索引分析案例1_单表优化

建表

create table article(
id int(10) unsigned not null primary key auto_increment,
author_id int(10) unsigned not null,
category_id int(10) unsigned not null,
views int(10) unsigned not null,
comments int(10) unsigned not null,
titles varchar(255) not null,
content text not null
);

插入数据

insert into  article (`author_id`, `category_id`, `views`, `comments`, `titles`, `content`) values('1', '1', '1', '1', '1', '1'),('2', '2', '2', '2', '2', '2'),('1', '1', '3', '3', '3', '3');

+----+-----------+-------------+-------+----------+--------+---------+
| id | author_id | category_id | views | comments | titles | content |
+----+-----------+-------------+-------+----------+--------+---------+
|  3 |         1 |           1 |     1 |        1 | 1      | 1       |
|  4 |         2 |           2 |     2 |        2 | 2      | 2       |
|  5 |         1 |           1 |     3 |        3 | 3      | 3       |
+----+-----------+-------------+-------+----------+--------+---------+
3 rows in set (0.00 sec)

案例分析

  • 查询出category_id为1 且comments大于1 的情况下views最多的zrticle
select id,author_id from article where category_id=1 and comments>1 order by views limit 1;

+----+-----------+
| id | author_id |
+----+-----------+
|  5 |         1 |
+----+-----------+

我们通过之前学习的explain 来分析一下

mysql> explain select id,author_id from article where category_id=1 and comments>1 order by views limit 1;
+----+-------------+---------+------+---------------+------+---------+------+------+-----------------------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra                       |
+----+-------------+---------+------+---------------+------+---------+------+------+-----------------------------+
|  1 | SIMPLE      | article | ALL  | NULL          | NULL | NULL    | NULL |    3 | Using where; Using filesort |
+----+-------------+---------+------+---------------+------+---------+------+------+-----------------------------+
1 row in set (0.02 sec)

改善:
1.我们发现 type为ALL 说明使用了全表扫描 这样就非常的不好我们查询一下索引

mysql> show index from article;
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table   | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| article |          0 | PRIMARY  |            1 | id          | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

我们看以看到只有一个主键,所以我们要新建索引,我们在where 后面的条件字段建立符合索引

create index idx_article_ccv on article(category_id,comments,views);
mysql> show index from article;
+---------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table   | Non_unique | Key_name        | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| article |          0 | PRIMARY         |            1 | id          | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |
| article |          1 | idx_article_ccv |            1 | category_id | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |
| article |          1 | idx_article_ccv |            2 | comments    | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |
| article |          1 | idx_article_ccv |            3 | views       | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |
+---------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
4 rows in set (0.00 sec)

可以看到我们成功的建立了索引,所以我们在查询一次

mysql> explain select id,author_id from article where category_id=1 and comments>1 order by views limit 1;
+----+-------------+---------+-------+-----------------+-----------------+---------+------+------+---------------------------------------+
| id | select_type | table   | type  | possible_keys   | key             | key_len | ref  | rows | Extra                                 |
+----+-------------+---------+-------+-----------------+-----------------+---------+------+------+---------------------------------------+
|  1 | SIMPLE      | article | range | idx_article_ccv | idx_article_ccv | 8       | NULL |    1 | Using index condition; Using filesort |
+----+-------------+---------+-------+-----------------+-----------------+---------+------+------+---------------------------------------+
1 row in set (0.00 sec)

观察我们的key 说明我们已经用到了索引,再看type已经变成了range,但是我们看extra出现了"文件排序" 之后我们会学习 order by 索引失效的问题 这样就说明了我们建立的索引不是很合适
删除我们的索引

mysql> drop index idx_article_ccv on article;
Query OK, 0 rows affected (0.11 sec)
Records: 0  Duplicates: 0  Warnings: 0



mysql> explain select id,author_id from article where category_id=1 and comments>1 order by views limit 1;
+----+-------------+---------+------+---------------+------+---------+------+------+-----------------------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra                       |
+----+-------------+---------+------+---------------+------+---------+------+------+-----------------------------+
|  1 | SIMPLE      | article | ALL  | NULL          | NULL | NULL    | NULL |    3 | Using where; Using filesort |
+----+-------------+---------+------+---------------+------+---------+------+------+-----------------------------+
1 row in set (0.00 sec)

我们发现type 又变成了全表扫描,也证明我们成功的删除了索引

结论

type变成了range是可以忍受的,但是extra里使用Using fukesort 文件排序是无法接受的,但是我们已经建立了索引.为什么会出现索引失效呢?

先看BTree工作原理:
我们先排序category_id索引,在进行查找当我们找到了category_id=1时
我们在排序comments 在进行查找符合的值,但**该条件是一个范围值(所谓的range)**也就造成了后面的views索引无法在进行检索.

重点:即range类型查询字段的索引无效

所以我们吸取上面的教训,再次建立索引,不在建立comments索引,绕过它去.

mysql> create index idx_article_cv on article(category_id,views);
Query OK, 0 rows affected (0.39 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from article;
+---------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table   | Non_unique | Key_name       | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| article |          0 | PRIMARY        |            1 | id          | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |
| article |          1 | idx_article_cv |            1 | category_id | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |
| article |          1 | idx_article_cv |            2 | views       | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |
+---------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)

我们在运行一下 explain

mysql> explain select id,author_id from article where category_id=1 and comments>1 order by views limit 1;
+----+-------------+---------+------+----------------+----------------+---------+-------+------+-------------+
| id | select_type | table   | type | possible_keys  | key            | key_len | ref   | rows | Extra       |
+----+-------------+---------+------+----------------+----------------+---------+-------+------+-------------+
|  1 | SIMPLE      | article | ref  | idx_article_cv | idx_article_cv | 4       | const |    2 | Using where |
+----+-------------+---------+------+----------------+----------------+---------+-------+------+-------------+
1 row in set (0.02 sec)

大功告成

哈哈 我们type不仅变成了ref 也没有了文件排序

猜你喜欢

转载自blog.csdn.net/weixin_39907636/article/details/85295900
今日推荐