建表语句

CREATE TABLE IF NOT EXISTS `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,
`title` VARBINARY(255) NOT NULL,
`content` TEXT NOT NULL
); INSERT INTO `article`(`author_id`, `category_id`, `views`, `comments`, `title`, `content`) VALUES
(1, 1, 1, 1, '1', '1'),
(2, 2, 2, 2, '2', '2'),
(1, 1, 3, 3, '3', '3');

查询索引

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)
  • Table
  • Non_unique: 非唯一索引(0为唯一索引, 1 为非唯一索引)
  • Key_name: 表示索引的名称
  • Seq_in_index: 表示该字段在索引中的位置,单列索引改值该值为1,组合索引为每个字段在索引中定义的顺序
  • Column_name: 列名
  • Collation: 字符序的规则
  • Cardinality: 基数
  • Sub_part: 表示索引的长度
  • Packed: 是否创建压缩的索引(1, 0 与 Default)
  • Null: 表示该字段是否能为空值
  • Index_type: 表示索引类型
  • Comment: 注释
  • Index_comment: 索引注释

用explain查询sql

mysql> explain select id, author_id from article where category_id = 1 and comments > 1 order by views DESC LIMIT 1;
+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-----------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-----------------------------+
| 1 | SIMPLE | article | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where; Using filesort |
+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-----------------------------+
1 row in set, 1 warning (0.00 sec)
  • 可以看到type为all(全表查询), Extra中有Using filesort(使用了外部索引排序, 而不是按照表内索引顺序进行读取)。
  • 需要进行优化, 不然数据量大后就比较危险。

创建复合索引

mysql> create index idx_article_ccv on article(category_id,comments,views);
Query OK, 0 rows affected (0.01 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_ccv | 1 | category_id | A | 2 | 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)
  • 再次使用explain查询sql

    mysql> explain select id, author_id from article where category_id = 1 and comments > 1 order by views DESC LIMIT 1;
    +----+-------------+---------+------------+-------+-----------------+-----------------+---------+------+------+----------+---------------------------------------+
    | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
    +----+-------------+---------+------------+-------+-----------------+-----------------+---------+------+------+----------+---------------------------------------+
    | 1 | SIMPLE | article | NULL | range | idx_article_ccv | idx_article_ccv | 8 | NULL | 1 | 100.00 | Using index condition; Using filesort |
    +----+-------------+---------+------------+-------+-----------------+-----------------+---------+------+------+----------+---------------------------------------+
    1 row in set, 1 warning (0.00 sec)
    • 可以看到type从all变成了range, 但是依旧走的外部索引排序, 而不是按照表内索引顺序进行读取。
    • 索引失效的原理:
      • 使用的是B+树
      • 先排序 category_id
      • 如果遇到相同的 category_id 则再排序 comments, 如果遇到相同的 comments 则再排序 views。
      • 当 comments 字段在联合索引里处于中间位置时, 因comments > 1 条件是一个范围值(所谓range)
      • MySQL 无法利用索引再对后面的 views 部分进行检索, 即range 类型查询字段后面的索引无效。

删除原先索引, 构建新索引

  • 删除索引
drop index idx_article_ccv on article;
  • 创建新索引(避开了有范围条件的comments, 从而不会造成索引失效)
create index idx_article_cv on article(category_id, 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_cv | 1 | category_id | A | 2 | NULL | NULL | | BTREE | | |
    | article | 1 | idx_article_cv | 2 | views | A | 3 | NULL | NULL | | BTREE | | |
    +---------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    3 rows in set (0.00 sec)
  • 再次使用explain查看sql语句

    explain select id, author_id from article where category_id = 1 and comments > 1 order by views DESC LIMIT 1;
    +----+-------------+---------+------------+------+----------------+----------------+---------+-------+------+----------+-------------+
    | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
    +----+-------------+---------+------------+------+----------------+----------------+---------+-------+------+----------+-------------+
    | 1 | SIMPLE | article | NULL | ref | idx_article_cv | idx_article_cv | 4 | const | 2 | 33.33 | Using where |
    +----+-------------+---------+------------+------+----------------+----------------+---------+-------+------+----------+-------------+
    1 row in set, 1 warning (0.00 sec)
    • 可以看到type变为了ref, extra中的file sorting消失了。

mysql 单表索引优化的更多相关文章

  1. mysql 两表索引优化

    建表语句 CREATE TABLE IF NOT EXISTS `class`( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `card` INT(1 ...

  2. mysql 高级和 索引优化,目的:查的好,查的快,性能好

    1-事物隔离级别: 更新丢失, 并发情况下,对同一字段进行更新,就会出现更新丢失,采用乐观锁,比较版本号或时间戳可解决 读未提交 解决了更新丢失但是会引起脏读, 二个session.sessionA中 ...

  3. MySQL 单表优化

    一.表字段优化 1.整数类型尽量使用 TINYINT.SMALLINT.MEDIUM_INT 而不是INT,非负数要加上UNSIGNED 2.VARCHAR的长度分配要合理,不要过大 3.时间字段不超 ...

  4. MySQL单表数据不超过500万:是经验数值,还是黄金铁律?

    今天,探讨一个有趣的话题:MySQL 单表数据达到多少时才需要考虑分库分表?有人说 2000 万行,也有人说 500 万行.那么,你觉得这个数值多少才合适呢? 曾经在中国互联网技术圈广为流传着这么一个 ...

  5. MySQL单表最大记录数不能超过多少?

    MySQL单表最大记录数不能超过多少? 很多人困惑这个问题.其实,MySQL本身并没有对单表最大记录数进行限制,这个数值取决于你的操作系统对单个文件的限制本身. 从性能角度来讲,MySQL单表数据不要 ...

  6. MySQL单表数据不要超过500万行:是经验数值,还是黄金铁律?

    本文阅读时间大约3分钟. 梁桂钊 | 作者 今天,探讨一个有趣的话题:MySQL 单表数据达到多少时才需要考虑分库分表?有人说 2000 万行,也有人说 500 万行.那么,你觉得这个数值多少才合适呢 ...

  7. MySQL单表最大限制

    想把一个项目的数据库导出来,然后倒入到自己熟悉的MySQL数据库中进行运行和调试.导出来后,发现sql文件整整有12G多大,忽然想起来,MySQL好像有个叫做容量限制的神奇特性,但是忘了上限是多少了, ...

  8. mysql单表大小的限制

    mysql单表大小的限制一.MySQL数据库的MyISAM存储 引擎单表大小限制已经不是有MySQL数据库本身来决定(限制扩大到64pb),而是由所在主机的OS上面的文件系统来决定了.在mysql5. ...

  9. MySQL中的索引优化

    MySQL中的SQL的常见优化策略 MySQL中的索引优化 MySQL中的索引简介 过多的使用索引将会造成滥用.因此索引也会有它的缺点.虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行 ...

随机推荐

  1. Cisco AP-了解AP镜像

    Understanding Access Point OS Images IntroductionAll Cisco Aironet 802.11a/b/g/n and 11ac Wave 1 wir ...

  2. 迭代器对象numpy.nditer在数组上进行迭代——修改数组的值

    nditer对象有另一个可选参数op_flags,默认情况下,nditer将视待迭代遍历的数组为只读对象(read-only),为了在遍历数组的同时,实现对数组元素值得修改,必须指定op_flags= ...

  3. linux动态监控dstat&&glances&&psutil&&bottle

    安装dstat yum install dstat 安装glances yum install python-devel pip install glances 如果我们安装了 Bottle 这个 w ...

  4. 前端学习 之 CSS(三)

    九:浮动 浮动是css里面布局最多的一个属性,也是很重要的一个属性. float:表示浮动的意思. 属性值: none: 表示不浮动,默认 left: 表示左浮动 right:表示右浮动 例: htm ...

  5. 设计模式课程 设计模式精讲 5-2 工厂方法coding

    1 课堂讲义 1.1 产品等级和产品簇 2 代码演练 2.1 工厂方法代码演练 1 课堂讲义 1.1 产品等级和产品簇 工厂方法是为了解决同一产品等级的业务抽象问题 抽象工厂方法是为了解决同一产品簇的 ...

  6. 软件架构,WEB - REST架构,RESTful API

    参考 https://www.zhihu.com/question/27785028/answer/48096396 wiki太学术化了 http://www.ruanyifeng.com/blog/ ...

  7. hadoop程序理解

    1.利用hadoop的API写程序 驱动程序中利用hadoop的API,获取配置,默认会根据HADOOP_HOME环境变量指定的HADOOP主目录下/etc/hadoop加载配置文件 2.启动利用 - ...

  8. 如何用C++读取图片中的像素

    来源:https://bbs.csdn.net/topics/391956973  3楼 #include <iostream> #include <fstream> #inc ...

  9. Windows程序设计学习笔记(1):一个简单的windows程序

    <Windows程序设计>(第五版)(美Charles Petzold著) #include<windows.h> LRESULT CALLBACK WndProc(HWND, ...

  10. 代码审计变成CTF

    0x01 代码审计中的信息收集 一个cms代码量确实不少,通读代码耗时长,效果也不一定好.而一个功能点如果之前出过漏洞,特别是多次出现漏洞的地方,证明开发者对这个漏洞的理解不充分,很容易再次绕过补丁. ...