建表语句

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. 802.1X基本配置

    基本的802.1X部署工作包括以下4步:    1. 为Cisco Catalyst交换机配置802.1X认证方    2. 为交换机配置访客VLAN或者受限VLAN,并调整802.1X定时器(可选) ...

  2. 2016-2017学年第三次测试赛 习题H MCC的考验

    问题 H: MCC的考验 时间限制: 1 Sec  内存限制: 128 MB 题目描述 MCC男神听说新一期的选拔赛要开始了,给各位小伙伴们带来了一道送分题,如果你做不出来,MCC会很伤心的. 给定一 ...

  3. java判断字符串是否是数字

    正则表达式 代码如下: public static boolean isNum(String num){ return num.matches("(\\s)*([+-])?(([0-9]*\ ...

  4. leetCode练题——26. Remove Duplicates from Sorted Array

    1.题目 26. Remove Duplicates from Sorted Array--Easy Given a sorted array nums, remove the duplicates  ...

  5. if 条件的 true / false 及 select 的值

    if 条件的 true / false 任何不是 false, undefined, null, 0, NaN 的值,或一个空字符串('')在作为条件语句进行测试时实际返回true,因此您可以简单地使 ...

  6. HDU 2680 最短路 迪杰斯特拉算法 添加超级源点

    Choose the best route Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  7. ubuntu 更改pip默认源

    mkdir ~/.pip vim ~/.pip/pip.conf [global] timeout = 6000 https://pypi.tuna.tsinghua.edu.cn/simple 保存 ...

  8. PCF8591 AD/DA模块使用详解

    I2C PCF8591 8位AD/DA转换 BCM2835 Library 1.PCF8591T简述 PCF8591器件图如下: PCF8591是一个8位的CMOS数据采集器件,具有4个模拟输入(其中 ...

  9. Session共享解决方案

    使用nginx做的负载均衡添加一个ip_hash配置 一.开两个Tomcat写测试程序 @WebServlet("/nginxSessionServlet") public cla ...

  10. Vue中 关于 ‘...mapGetters’的了解

    首先,我们应该知道getters是vuex中的特殊表达部分 不使用map辅助函数: computed: { test:()=> this.$store.getters.doSome } 使用ma ...