建表语句

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. js指定范围指定个数的不重复随机数

    今天偶然看到的 比如要生成 1-100范围之内的10个不重复随机数,代码就可以这么写 var arr = []; for (var i = 1; i <=100; i++) { arr.push ...

  2. idea maven项目使用过程中遇到的问题

    1. Error:Cannot build Artifact :war exploded because it is included into a circular depency 参考: http ...

  3. 【原】linux两台服务器之间免密登录方法

    搭建集群机器192.168.0.100和192.168.0.200里,需要两台机器中间相互拷贝文件: 方式一:下载192.168.0.100机器文件到本地,再将本地文件拷贝到B机器 方式二:192.1 ...

  4. kafka中常用API的简单JAVA代码

    通过之前<kafka分布式消息队列介绍以及集群安装>的介绍,对kafka有了初步的了解.本文主要讲述java代码中常用的操作. 准备:增加kafka依赖 <dependency> ...

  5. Web基础了解版09-Cookie-Session

    Cookie Cookie 是一种服务器发送给浏览器以键值对形式存储小量信息的技术. 当浏览器首次请求服务器时,服务器会将一条信息封装成一个Cookie发送给浏览器,浏览器收到Cookie,会将它保存 ...

  6. 语言国际化:中文ASC码互转

    https://javawind.net/tools/native2ascii.jsp 1.首先找到了上面的链接,也就是下图,输入中文就可立即得出ASCII码 2.看到上图第一条,找到了JDK/bin ...

  7. 解决安装PyMySQL一直停在Building wheels for collected package:cryptography, cffi, pycparser的问题

    我的运行环境为: 硬件:树莓派3b 系统:ubuntu_meta_16.04.2 因为项目需要,我在树莓派上搭建了基于python编程的Django的web框架,需要从MySQL中读取树莓派以及传感器 ...

  8. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:移除默认的列表样式

    <!DOCTYPE html> <html> <head> <title>菜鸟教程(runoob.com)</title> <meta ...

  9. 找出crontab表达式内符合的下一次出发时间点(经典!!!)

    参考: https://blog.csdn.net/crazycoder2010/article/details/7905848

  10. Codeforces Global Round 4E(字符串,思维)

    #include<bits/stdc++.h>using namespace std;string s,a,b;int main(){ cin>>s; int n=s.size ...