Mysql优化(出自官方文档) - 第八篇(索引优化系列)
Mysql优化(出自官方文档) - 第八篇(索引优化系列)
Optimization and Indexes
正确的创建索引往往会加快查询速度,但是,没有必要的索引往往只会浪费空间,并且增加插入,更新和删除的开销,因为进行这些操作要同时更新索引。
但是,索引并不是万能的,在下面的几个场景中,索引将会显得不是那么有用:
- 小表,或者大表,但是需要请求所有行
- 当一个请求需要表中的大部分行时,连续读往往效率会比索引高,因为连续读会减少磁盘seek的时间。
1 Foreign Key Optimization
如果经常读取一个表中的多个列,那么,把最少访问的列分出来单独作为一个小表,然后使用外键的方式和主表联系起来,这样子在读取数据的时候就能尽量减少磁盘的I/O读写。
2 Column Indexes
Index Prefixes
Mysql允许只使用一些字段的一部分来作为索引,这其中包括所有的
TEXT
和BLOB
字段,如下面的例子:CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));
需要注意的是,对于
CHAR, VARCHAR, TEXT
类型的字段,长度为字符个数的意思,但是对于非字符串字段,如BINARY, VARBINARY, BLOB
字段,长度为字节个数的意思。FULLTEXT Indexes
该索引适用于
CHAR
,VARCHAR
, andTEXT
的列,并且全文索引不支持前缀,只支持全列的索引。当查询符合如下特征的时候,全文索引将会非常有用:FULLTEXT
查询语句值需要document ID
或者search rank
(分级??)FULLTEXT
查询语句对查询到的结果进行一个降序排序,并且有一个LIMIT
语句选取top N
项,这种情况下为了使用优化必须保证查询语句没有WHERE
且ORDER BY
只有一列。FULLTEXT
查询只获取COUNT(*)
的结果,且没有WHERE
语句,如果需要WHERE
过滤,请将WHERE
写为WHERE MATCH(TEXT) AGAINST('other_text')
,并且没有任何> 0
的比较操作符。
Indexes in the MEMORY Storage Engine
对于内存存储引擎,默认使用
HASH
索引,但是同样也支持BTREE
索引。
3 Column Indexes && Multiple-Column Indexes
Mysql支持单独的一列作为索引,也可以使用多列作为索引,当使用多列的时候,使用最左边(leftmost prefix of the index)的列进行查询,可以用到索引,否则,Mysql将无法使用索引,举例如下:
假设一个表含有下面的索引:
INDEX name (last_name,first_name)
对于下面的查询语句都可以使用到name索引:
SELECT * FROM test WHERE last_name='Jones';
SELECT * FROM test
WHERE last_name='Jones'
AND (first_name='John' OR first_name='Jon');
SELECT * FROM test
WHERE last_name='Jones'
AND first_name >='M' AND first_name < 'N';
下面的语句因为没有使用最左边的列进行查询,所以无法使用索引:
SELECT * FROM test WHERE first_name='John';
SELECT * FROM test
WHERE last_name='Jones' OR first_name='John';
假设有两列col1
和col2
,如果索引刚好建在col1
和col2
上,那么可以直接使用索引,但是如果col1
和col2
是单独的索引(即不是多列索引),那么Mysql会尝试使用 Index Merge optimization
(see Section 8.2.1.3, “Index Merge Optimization”)技术,或者判断两个索引中哪个的条件是最严苛的,能够排除尽可能的行,在决定使用哪个索引。
4 Comparison of B-Tree and Hash Indexes
B-Tree Index Characteristics
B树索引支持
=
,>
,>=
,<
,<=
, orBETWEEN
操作符,也支持LIKE
操作符,但是必须保证LIKE
字段不是以通配符开头的。如果一个索引没有覆盖所有的
AND
,那么Mysql将无法使用该索引,换句话说,为了能够使用到该索引,必须保证一个索引的前缀(最左边部分)出现在每一个AND
中,举例如下:... WHERE index_part1=1 AND index_part2=2 AND other_column=3 /* index = 1 OR index = 2 */
... WHERE index=1 OR A=10 AND index=2 /* optimized like "index_part1='hello'" */
... WHERE index_part1='hello' AND index_part3=5 /* Can use index on index1 but not on index2 or index3 */
... WHERE index1=1 AND index2=2 OR index1=3 AND index3=3;
下面的语句将无法使用索引:
/* index_part1 is not used */
... WHERE index_part2=1 AND index_part3=2 /* Index is not used in both parts of the WHERE clause */
... WHERE index=1 OR A=10 /* No index spans all rows */
... WHERE index_part1=1 OR index_part2=10
(这里不是很懂?)
需要注意的是:
Mysql并不会任何时候都选择使用索引,有的时候,当需要读取特别多的行时,使用索引的效率可能要低于
table scan
的效率,因为索引会导致磁盘出现更多的寻道消耗,而table scan
由于是连续读,则能更大效率的利用磁盘I/OHash Index Characteristics
Hash
索引相对比于B
树索引,可能会出现下面的不同:Hash
索引只能用于=
或者<=>
操作符,不能用于范围查询- 优化器无法使用
Hash
索引来加速ORDER BY
操作 Mysql
无法评估两个value
之间有多少行(BETWEEN
语句)- 只有完整的索引才能正常工作,不能像
BTREE
那样,使用leftmost prefix key
5 Use of Index Extensions
InnoDB会自动给二级索引增加primary key作为新的索引,这是在内部完成的,用户无法感知,比如下面的表:
CREATE TABLE t1 (
i1 INT NOT NULL DEFAULT 0,
i2 INT NOT NULL DEFAULT 0,
d DATE DEFAULT NULL,
PRIMARY KEY (i1, i2),
INDEX k_d (d)
) ENGINE = InnoDB;
此时,对于索引k_d,其内部真正的实现方式为: (d, i1, i2)
. 即自动将primary key(i1, i2)添加到k_d后面构成新的二级索引。
这种优化方式,可用于ref
, range
和index_merge
的索引访问场景,Loose Index Scan
,join
和sort
,以及MIN()/MAX()。
比如下面的语句:
SELECT COUNT(*) FROM t1 WHERE i1 = 3 AND d = '2000-01-01'
此时由于内部将i1
添加到了k_d
索引,那么这条语句就可以使用到(d, i1)
这样的索引((d, i1)
是索引(d, i1, i2)
的最左边前缀),由于使用到了更多的列,所以需要扫描的行数将大大减少。
6 Invisible Indexes
这种索引指的是那种真实存在,但是优化器却不会使用的索引,只能对非primary key
进行该种设定,其他类型的索引均支持设置为INVISIBLE
。
例如下面的例子:
CREATE TABLE t1 (
i INT,
j INT,
k INT,
INDEX i_idx (i) INVISIBLE
) ENGINE = InnoDB;
CREATE INDEX j_idx ON t1 (j) INVISIBLE;
ALTER TABLE t1 ADD INDEX k_idx (k) INVISIBLE;
这种索引一般的用途:测试移除一个索引对于性能的影响,因为这种索引不是真正的将其移除了,只是优化器不再考虑该索引,所以并不会对表造成太大的影响。
注意虽然索引是Invisible
的,但是这种索引和普通索引一样具有完备的功能,也就是说增删改的时候,Mysql同样会更新Invisible Index
,同理,如果在一个非常大的表上创建Invisible Index
时,和普通索引一样,开销也是非常巨大的。
7 Descending Indexes
Mysql支持降序索引,不像以前的版本,索引定义里面的DESC不再被忽略,内部对于索引的存储方式也采取降序的方式;而在此之前,Mysql是采用对index进行逆序扫描的方式,当前采用降序的方式效率比以前要高很多。
使用降序索引主要针对下面的场景:
- 降序索引只支持InnoDB引擎,并且有如下限制:
- 如果一个二级索引有降序key或者说一个主键包含降序key,那么Mysql无法支持修改Buffering
- InnoDB的SQL解析器不会使用降序索引,对于full-text查询,这意味着已经被索引的表上面的
FTS_DOC_ID
列不能被定义为降序索引。
- 一个含有降序key的索引无法使用MIN/MAX优化,特指那种含有聚合函数但是却不带GROUP BY的语句。
- 降序索引只支持BTREE,并不支持HASH索引,降序索引无法支持FULLTEXT或者SPATIAL索引。
Mysql优化(出自官方文档) - 第八篇(索引优化系列)的更多相关文章
- Mysql优化(出自官方文档) - 第九篇(优化数据库结构篇)
目录 Mysql优化(出自官方文档) - 第九篇(优化数据库结构篇) 1 Optimizing Data Size 2 Optimizing MySQL Data Types 3 Optimizing ...
- Mysql优化(出自官方文档) - 第二篇
Mysql优化(出自官方文档) - 第二篇 目录 Mysql优化(出自官方文档) - 第二篇 1 关于Nested Loop Join的相关知识 1.1 相关概念和算法 1.2 一些优化 1 关于Ne ...
- Mysql优化(出自官方文档) - 第一篇(SQL优化系列)
Mysql优化(出自官方文档) - 第一篇 目录 Mysql优化(出自官方文档) - 第一篇 1 WHERE Clause Optimization 2 Range Optimization Skip ...
- Mysql优化(出自官方文档) - 第三篇
目录 Mysql优化(出自官方文档) - 第三篇 1 Multi-Range Read Optimization(MRR) 2 Block Nested-Loop(BNL) and Batched K ...
- Mysql优化(出自官方文档) - 第五篇
目录 Mysql优化(出自官方文档) - 第五篇 1 GROUP BY Optimization 2 DISTINCT Optimization 3 LIMIT Query Optimization ...
- Mysql优化(出自官方文档) - 第十二篇(优化锁操作篇)
Mysql优化(出自官方文档) - 第十二篇(优化锁操作篇) 目录 Mysql优化(出自官方文档) - 第十二篇(优化锁操作篇) 1 Internal Locking Methods Row-Leve ...
- Mysql优化(出自官方文档) - 第十篇(优化InnoDB表篇)
Mysql优化(出自官方文档) - 第十篇(优化InnoDB表篇) 目录 Mysql优化(出自官方文档) - 第十篇(优化InnoDB表篇) 1 Optimizing Storage Layout f ...
- Mysql优化(出自官方文档) - 第七篇
Mysql优化(出自官方文档) - 第七篇 目录 Mysql优化(出自官方文档) - 第七篇 Optimizing Data Change Statements 1 Optimizing INSERT ...
- Mysql优化(出自官方文档) - 第六篇
Mysql优化(出自官方文档) - 第六篇 目录 Mysql优化(出自官方文档) - 第六篇 Optimizing Subqueries, Derived Tables, View Reference ...
随机推荐
- 这样子来理解C语言中指针的指针
友情提示:阅读本文前,请先参考我的之前的文章<从四个属性的角度来理解C语言的指针也许会更好理解>,若已阅读,请继续往下看. 我从4个属性的角度来总结了C语言中的指针概念.对于C语言的一个指 ...
- 爬虫之突破xm-sign校验反爬
喜马拉雅 网页分析 - 打开我们要爬取的音乐专辑https://www.ximalaya.com/ertong/424529/ - F12打开开发者工具 - 点击XHR 随便点击一首歌曲会看到存储所有 ...
- 00ff00 颜色信息
RGB 0, 255, 0 百分比 0.0%, 100.0%, 0.0% 十六进制 00ff00 十进制 65280 二进制 00000000,11111111,00000000 CMYK 100.0 ...
- CF1027D Mouse Hunt题解
题目: 伯兰州立大学的医学部刚刚结束了招生活动.和以往一样,约80%的申请人都是女生并且她们中的大多数人将在未来4年(真希望如此)住在大学宿舍里. 宿舍楼里有nn个房间和一只老鼠!女孩们决定在一些房间 ...
- 个人用户永久免费,可自动升级版Excel插件,使用VSTO开发,Excel催化剂安装过程详解及安装失败解决方法
因Excel催化剂用了VSTO的开发技术,并且为了最好的用户体验,用了Clickonce的布署方式(无需人工干预自动更新,让用户使用如浏览器访问网站一般,永远是最新的内容和功能).对安装过程有一定的难 ...
- springBean生命周期----来自spring实战总结
1.Spring对bean进行实例化 2.Spring将值和bean的引用注入到bean对应的属性中(比如说注入到被依赖的bean的方法中或属性里) 3.如果bean实现了BeanNameAware接 ...
- Shiro在Web环境下集成Spring的大致工作流程
1,Shiro提供了对Web环境的支持,其通过一个 ShiroFilter 入口来拦截需要安全控制的URL,然后进行相应的控制. ①配置的 ShiroFilter 实现类为:org.spri ...
- ehcache的使用 Shiro与Ehcache的结合(附:EhcacheUtils)
ehcache 缓存的使用 合理的使用缓存会极大的提高程序的运行效率.切记:缓存请勿滥用. 配置ehcache与Shiro shiro初识请查看该文章 https://blog.csdn.net/py ...
- C#3.0新增功能08 Lambda 表达式
连载目录 [已更新最新开发文章,点击查看详细] Lambda 表达式是作为对象处理的代码块(表达式或语句块). 它可作为参数传递给方法,也可通过方法调用返回. Lambda 表达式广泛用于: 将 ...
- Linux系统安装jdk——.tar.gz版
1.rpm.deb.tar.gz的区别: rpm格式的软件包适用于基于Red Hat发行版的系统,例如Red Hat Linux.SUSE.Fedora. deb格式的软件包则是适用于基于Debian ...