索引的建立及优化-单表分析


1.单表优化

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for article
-- ----------------------------
DROP TABLE IF EXISTS `article`;
CREATE TABLE `article` (
`id` int(10) NOT NULL,
`author_id` int(10) NOT NULL,
`category_id` int(10) NOT NULL,
`views` int(10) NOT NULL,
`comments` int(10) NOT NULL,
`title` varbinary(255) NOT NULL,
`content` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of article
-- ----------------------------
INSERT INTO `article` VALUES (1, 1, 1, 1, 1, 0x31, '1');
INSERT INTO `article` VALUES (2, 2, 2, 2, 2, 0x32, '2');
INSERT INTO `article` VALUES (3, 1, 1, 3, 3, 0x33, '3');

SET FOREIGN_KEY_CHECKS = 1;

查询case
1.查询category_id为1且comments大于1的情况下,views最多的article_id

EXPLAIN  SELECT  id  FROM  article WHERE category_id=1 and comments >1 ORDER BY views DESC LIMIT 1

结论
type为ALL全表扫描,Extra中有Using filesort 文件排序 必须优化
优化
1.建立联合索引
CREATE INDEX index_article_ccv ON article(category_id,comments,views)

查询优化结果
EXPLAIN  SELECT  id  FROM  article WHERE category_id=1 and comments >1 ORDER BY views DESC LIMIT 1

解决了全表扫描的问题,但是没有解决Using filesort的问题,试试将comments>1 改为comments=1则
EXPLAIN  SELECT  id  FROM  article WHERE category_id= 1 and comments = 1 ORDER BY views DESC LIMIT 1

结论:

type变成range,这是可以忍受的。但是extra里使用Using filesort仍然无法接受的。但是我们已经建立了索引,为啥没用呢?

这是因为按照BTree索引的工作原理,先排序category_id,如果遇到相同的category_id,则再排序comments,如果遇到相同的comments则再排序views。

当comments字段在联合索引中处于中间位置时,因为comments>1条件是一个范围值(所谓range)

MySQL无法利用索引对后面的views部分进行检索,即range类型查询字段后面的索引无效

说明comments>1导致后面的索引没有用上,当前索引不合适 删除索引
DROP INDEX index_article_ccv ON article
查看查询
EXPLAIN  SELECT  id  FROM  article WHERE category_id= 1 and comments > 1 ORDER BY views DESC LIMIT 1

那我们建立索引去掉中间的comments字段直接category_id以及views字段建立联合索引
CREATE INDEX index_article_cv  ON article(category_id,views)

查看索引
SHOW INDEX FROM article

查看查询
EXPLAIN  SELECT  id  FROM  article WHERE category_id=1 and comments > 1 ORDER BY views DESC LIMIT 1

 

结论
type也达到了更好的ref,同时filesort 文件排序也消失了,得到了较好的优化