索引对提升SELECT/UPDATE语句查询速度有着立竿见影的效果,有索引和无索引,查询速度往往差几个数量级。

本次讨论一下index(每列作为一个索引,单列索引)和Multiple-Column Indexes(多列作为一个索引,最多16列,复合索引)使用场景。

常见新建或添加索引的方式:

方式一,建表时新建

CREATE TABLE test (
id INT NOT NULL,
last_name CHAR(30) NOT NULL,
first_name CHAR(30) NOT NULL,
PRIMARY KEY (id),
-- 单列索引
INDEX name (last_name)
-- 复合索引
-- INDEX name (last_name,first_name)
);

方式二,给即存表添加索引:

/*单列索引*/
ALTER TABLE test ADD INDEX name (last_name);
/*复合索引*/
ALTER TABLE test ADD INDEX name (last_name,first_name);

这里要注意索引的顺序很重要,关系到能否命中索引,后面详细讨论。

mysql官方文档是这么描述复合索引的:mysql能使用复合索引来查询索引中的所有列,或者查询复合索引中的第一列、前两列、前三列等等。

如果指定列顺序正确相对于索引中的定义顺序,那么一个简单的复合作引可以加快一个表中几种类型的查询。官网地址

以上这段话包可解读如下:

  • 复合索引的优点:一个复合索引解决多种查询的效率问题
  • 复合索引的命中规则:前半句话描述的是命中复合索引的最左前缀(leftmost prefix)规则,也就是上面提到的索引顺序问题。这个规则是对于WHERE语句中的索引列的顺的。

简单的说加入复合索引的顺序是(col1, col2, col3)那么WHERE语句中的(col1)、(ol1, col2)、(col1, col2, col3)都能命中索引,但是(col2)、(col3)、(ol2, col3)是不能命中索引规则的,因为不满足最左前缀规则。

举个栗子,假设新建复合索引如下:

CREATE TABLE test (
id INT NOT NULL,
last_name CHAR(30) NOT NULL,
first_name CHAR(30) NOT NULL,
PRIMARY KEY (id),
INDEX name (last_name,first_name)
);

根据最左前缀原则,以下查询语句能命中索引:

SELECT * FROM test WHERE last_name='Widenius';

SELECT * FROM test
WHERE last_name='Widenius' AND first_name='Michael'; SELECT * FROM test
WHERE last_name='Widenius'
AND (first_name='Michael' OR first_name='Monty'); SELECT * FROM test
WHERE last_name='Widenius'
AND first_name >='M' AND first_name < 'N';

以下查询语句不能命中复合索引:

SELECT * FROM test WHERE first_name='Michael';

SELECT * FROM test
WHERE last_name='Widenius' OR first_name='Michael';

如果不清楚是否命中索引,EXPLAIN是个好工具,要充分利用起来。比如下语句,查看结果中的key就能知道是否命中,为空就是木有命中:

EXPLAIN SELECT * FROM test WHERE first_name='Michael';

使用场景:

在做报表集计一般会使用ETL工具抽取业务数据插入到事实表中,就比如使用kettle update/insert,其内部原理都是先查询不存在就如插入数据,存在数据就更新。

因此如果数据很多的话就会有很多的查询动作,并且是多条件查询。这种情况复合索引效率是最高的,但是往往实际的业务中还会以单列作为查询的场合这是就需要普通索引来满足这个需求。

这种场合就会出现同一列同时出现在了复合索引和单列索引中,这也是很正常的。给一个实际的例子如下:

CREATE TABLE `st_stock` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`id_company` int(11) NOT NULL COMMENT '组织维度',
`id_date` int(11) NOT NULL COMMENT '日期维度',
`id_part` int(11) NOT NULL COMMENT '材料维度',
`number` decimal(18,2) DEFAULT NULL COMMENT '出库数量',
`subtotal` decimal(21,6) DEFAULT NULL COMMENT '出库金额',
PRIMARY KEY (`id`),
KEY `IDX_ORG` (`id_company`),
KEY `IDX_PART` (`id_part`),
KEY `IDX_DATE_ORG_PART` (`id_date`,`id_company`,`id_part`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='xxxxxx';

实际疗效:

#2498和#2499数据量大于等于#2496、#2497,但集计时间将近缩短了一半,效果还是很明显。

优化效果没有达到一个数量或更高级是因为优化的只是JOB中一个转换,只是优化的众多因素之一。

即便如此也达到了预期的效果。

最后还要注意一点,索引的维护是有代价的,并不是越多越好。其他参考资料如下:

https://www.percona.com/blog/2009/09/19/multi-column-indexes-vs-index-merge/

https://www.percona.com/blog/2014/01/03/multiple-column-index-vs-multiple-indexes-with-mysql-56/

https://dev.mysql.com/doc/refman/5.7/en/drop-index.html

https://dev.mysql.com/doc/refman/5.6/en/multiple-column-indexes.html

https://dev.mysql.com/doc/refman/5.7/en/create-index.html

mysql中index与Multiple-Column Indexes区别与联系的更多相关文章

  1. Mysql中unique与primary约束的区别分析(转)

    本文章来给大家介绍在mysql中unique与primary约束的区别分析,unique与primary是我们在创建mysql时常用的类型了,下面我来给大家介绍介绍.   定义了UNIQUE约束的字段 ...

  2. 万答#11,MySQL中char与varchar有什么区别

    万答#11,MySQL中char与varchar有什么区别 1.实验场景 GreatSQL 8.0.25 InnoDB 2.实验测试 2.1 区别 参数 char varchar 长度是否可变 定长 ...

  3. mysql函数count(*)和count(column)的区别(转)

    mysql中count(*)和count(column)使用是有区别的: count(*)对行的数目进行计算,包含NULL count(column)对特定的列的值具有的行数进行计算,不包含NULL值 ...

  4. MySQL中index和key的关系

    KEY is normally a synonym for INDEX. The key attribute PRIMARY KEY can also be specified as just KEY ...

  5. mysql中in和exists二者的区别和性能影响

    mysql查询语句in和exists二者的区别和性能影响 还记得一次面试中被人问到in 和 exists的区别,当然只是草草做答,现在来做下分析. mysql中的in语句是把外表和内表作hash 连接 ...

  6. mysql中where和having子句的区别和具体用法

    1.mysql中的where和having子句的区别 having的用法 having字句可以让我们筛选成组后的各种数据,where字句在聚合前先筛选记录,也就是说作用在group by和having ...

  7. 正确理解MySQL中的where和having的区别

    原文:https://blog.csdn.net/yexudengzhidao/article/details/54924471 以前在学校里学习过SQLserver数据库,发现学习的都是皮毛,今天以 ...

  8. Mysql 中is null 和 =null 的区别

    在mysql中,筛选非空的时候经常会用到is not null和!=null,这两种方法单从字面上来看感觉是差不多的,其实如 果去运行一下试试的话差别会很大! 为什么会出现这种情况呢? null 表示 ...

  9. mysql中 date datetime time timestamp 的区别

    MySQL中关于时间的数据类型:它们分别是 date.datetime.time.timestamp.year date :"yyyy-mm-dd"  日期     1000-01 ...

  10. Mysql中的in和find_in_set的区别?

    在mysql中in的使用情况如下: select * from article where 列名 in(值1,值2,值3.....): select * from article where 值1 i ...

随机推荐

  1. you

    抑制幽门螺旋杆菌: 1.西兰花 鲜嫩的西兰花蔬菜,含有一种物质叫异硫氰酸酯,这种物质就是幽门螺杆菌的 " 天敌 ",可达到百分百抑制的作用,甚至还有医生给了它一个最强天然抗生素的称 ...

  2. [vue]vue条件渲染v-if(template)和自定义指令directives

    条件渲染: v-if/template <div id="app"> <h1>v-show: display: none</h1> <di ...

  3. PAT 1103 Integer Factorization[难]

    1103 Integer Factorization(30 分) The K−P factorization of a positive integer N is to write N as the ...

  4. 重读《Java编程思想》

    相关最新代码已上传至我的GitHub了(https://github.com/WenyangSun/ThinkingInJava),后续例子没有在博客上更新. 1.在类的内部,变量定义的先后顺序决定了 ...

  5. container / pull-left

    <div class="container"> <h2>实例</h2> <div class="pull-left"& ...

  6. inline详解

    1. 引入inline关键字的原因 在c/c++中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了inline修饰符,表示为内联函数. 栈空间就是指放置程序的局部数据(也就是 ...

  7. liferay中如何实现自己定义的方法

    大家看到这篇文章是不是很开心啊,我感觉是很开心,我们终于可以按照自己的意愿来写一次代码,在liferay中一些基本的增删改查的代码是自动生成的,然而我们想要实现自己的方法的话,恐怕要费一点劲,你要知道 ...

  8. zw版【转发·台湾nvp系列Delphi例程】HALCON SetComprise1

    zw版[转发·台湾nvp系列Delphi例程]HALCON SetComprise1 procedure TForm1.Button1Click(Sender: TObject);var image0 ...

  9. cf428c 模拟题

    这题说的是给了 n个数然后又 k次 的交换任意位置的 数字的机会  计算最长的连续子序列的和 这要撸  模拟整个 过程 并不能就是算最长的递增序列 如果只是 找最长的 和序列的 话 会存在 很多问题 ...

  10. uva10003

    /* 2014.3.6 这题说的是给你了一根木棒 然后 n 个点(线段上的点) 然后计算 在这 n个点上都切下去的 最小花费 举个例子 100 3 25 50 75 如果 从 25 开始切 然后切 5 ...