索引对提升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. jQuery内部原理和实现方式浅析

    这篇文章主要介绍了jQuery内部原理和实现方式浅析,本文试图从整体来阐述一下jQuery的内部实现,需要的朋友可以参考下 这段时间在学习研究jQuery源码,受益于jQuery日益发展强大,研究jQ ...

  2. 登录mysql出现/var/lib/mysql/mysql.sock不存在

    问题描述: 1.mysql安装完成后,使用 service mysqld start 总是出现 start failed. 2.使用mysql -uroot -p登录出现找不到 /var/lib/my ...

  3. 纯代码实现WordPress上传图片自动重命名的方法

    在我们使用 WordPress 发布文章时,经常都需要添加图片.多媒体什么的.然而,大家都知道 WordPress 是舶来物,对于中文用户来说,我们都会把图片命名为中文的,由于 WordPress 机 ...

  4. PAT Counting Leaves[一般]

    1004 Counting Leaves (30)(30 分) A family hierarchy is usually presented by a pedigree tree. Your job ...

  5. soapUI-Properties

    1.1.1  Properties 1.1.1.1 概述 - Properties Option Description   Toolbar 属性TestStep工具栏   Properties Li ...

  6. 使用fiddler对手机APP进行抓包

    在做手机或移动端APP的接口测试时,需要从开发人员那里获取接口文档,接口文档应该包括完整的功能接口.接口请求方式.接口请求URL.接口请求参数.接口返回参数.如果当前项目没有接口文档,则可以使用fid ...

  7. java判断包含contains方法的使用

    java中contains方法是判断是否存在包含关系,比如说a =[1,2,3,4], b=1那么a就包含b contains返回的是布尔类型true 和false,包含的话就返回true,不包含的话 ...

  8. http协议基础(二)请求和响应报文的构成

    http协议用于客户端和服务器之间的通信,请求访问资源的一方称为客户端,而提供资源响应的一方称为服务器端. 下面就是客户端和服务端之间简单的通信过程 PS:请求必须从客户端建立通信,服务端没收到请求之 ...

  9. Q_UNUSED

    Q_UNUSED() 没有实质性的作用,用来避免编译器警告 void func( int a) { Q_UNUSED(a); //函数体内没有使用a,避免编译器警告 }

  10. Lower Power with CPF(四)

    CPF从Front-end到Back-end(RTL--GDSII)的整个流程: 1)Creating a CPF file:来在前端就建立lower power的规范. 2)检查CPF文件的正确性, ...