索引对提升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. idea 连接数据库

    1:如果没有数据库连接插件,下载database插件 settings>plugin>Database Navigator 下载. 2:重启 3:进入 view>tool windo ...

  2. CentOS6.5安装RHadoop

    1.首先安装依赖包(各个节点都要安装) [root@Hadoop-NN-01 ~]$ yum install gcc-gfortran #否则报”configure: error: No F77 co ...

  3. testng入门教程6 TestNG忽略测试

    有时,我们的代码是没有准备好,如果测试用例写入到测试方法/代码将无法运行,在这种情况下,@Test(enabled = false)有助于禁用此测试案例. 测试方法是标注了@Test(enabled ...

  4. iOS开发--图片轮播

    直接上代码了,比较简单.演示下载地址:Demo // // UYViewController.m // 图片轮播器 // // Created by jiangys on 15/5/23. // Co ...

  5. 如何提取app软件的apk格式中的字体?

    1.下载apk格式的指定app软件: 2.将apk格式的文件名更改为后缀名为zip格式: 3.用winrar解压软件解压,然后就找到其中的ttf格式的字体文件. 举例说明,我想找到airbnb的app ...

  6. JNDI—目录接口名

    1:什么是JNDI? Java名称与目录接口:java Naming and Directory Interface未开发人员提供的查找和访问各种名称和目录的 服务和接口 2:全局的上下文配置文件: ...

  7. Linux root用户下强制静音的问题

    解决方法 pulseaudio --start --log-target=syslog suorce /etc/profile

  8. python 多进程并发接口测试实例

    #encoding=utf-8 import requests import json import os import hashlib print "register------" ...

  9. Linux服务器---使用mysql

    使用mysql 1.登录,可以用密码登录,也可以不用密码登录.命令格式“mysql –u 用户名 –p 密码” [root@localhost src]# mysql -u root –p     / ...

  10. 2018年星际争霸AI挑战赛–三星与FB获冠亚军,中科院自动化所夺得季军

    雷锋网 AI 科技评论消息,2018 年 11 月 13-17 日,AAAI 人工智能与交互式数字娱乐大会 (AI for Interactive Digital Entertainment) 在阿尔 ...