高性能MySQL--索引学习笔记(原创)
看过一些人写的学习笔记,完全按书一字不漏照抄,内容很多,真不能叫笔记。遂自己整理了一份,取其精要。
更多笔记请访问@目录
索引概述
索引即key
在存储引擎层实现,不同引擎工作方式不同
索引优化--最好的查询优化手段,可提效几个数量级
两步查找数据:
磁盘查找索引节点(页),将其调入内存;
内存内业内查找数据
一. 索引类型
B-Tree
Hash
R-Tree空间数据索引
全文索引
1. B-tree索引
- 支持引擎:InnoDB,MyISAM,Memory
- 所有叶子值顺序存储,且到root高度一样
- InnoDB,MyISAM B-tree工作方式异同:
InnoDB按原格式存储数据,MYISAM用前缀压缩技术
InnoDB用主键key索引数据行,MyISAM用物理位置索引数据行
- 加速:存储引擎从root节点扫描,代替全表扫描
- 叶节点指针-->被索引数据(data record)
1)B-Tree适用场景
1 全值匹配查询
所有列都匹配
2 最左前缀匹配
组合索引第一列
3 列前缀匹配
某列值开头
4 范围值匹配
5 一列精确一列范围匹配
6 覆盖索引查询
只访问索引即可取data,无须访问数据行
7 Order by排序
?
2) B-Tree不适用场景
- 非最左列
- 跳列
A C
- 某列进行范围查询,其右边所有列无法再用索引
2. Hash索引
- 访问哈希索引的数据很快
f(key)=slot
1) 支持引擎
Memory,NDB集群
2) 适用场景
索引全列匹配
3) 不适用场景
- 不能从索引直接取data
哈希索引=哈希值+行指针,不存储字段值
- 不能用于排序
哈希值有序,但索引数据无序
- 不支持部分索引列匹配
- 不支持范围查询
仅支持等值匹配 =,<=>,IN()
<=> NULL安全等于----操作数可为NULL
4) InnoDB自适应Hash索引
某些索引值被引用很频繁,InnoDB自动在内存B-Tree索引上创建一个Hash索引
用户无法控制和配置,但可关闭
5) 自定义hash索引
存储引擎不支持时,模拟创建hash
如何创建?
B-tree上创建伪hash索引
- 仍在Btree上查找,但用hash索引值代替原Key(伪hash)
- 须在where指定hash函数,不要用MD5(),SHA1()
select id from url
where url="www.mysql.com"
and
url_crc=CRC32("www.mysql.com")
其中urc_crc列为索引列
6) 处理Hash冲突
使用hash索引查询时,须在where指定常量
select id from url
where
url_crc=CRC32("www.mysql.com")
and
url="www.mysql.com"
select word,crc from words
where
crc=CRC32("gnu")
and
word="gnu"
@birthday problem
In probability theory, the birthday problem or birthday paradox concerns the
probability that,
in a set of {\displaystyle n} n randomly chosen people, some pair of them will have the same birthday.
By the pigeonhole principle, the probability reaches 100% when the number of people reaches 367 (since there are only 366 possible birthdays, including February 29). However, 99.9% probability is reached with just 70 people, and 50% probability with 23 people.
3. 空间数据索引 R-Tree
支持引擎:MyISAM
用作地理数据存储,如美团,滴滴定位服务
任意维度组合查询
须使用GIS函数维护数据,MySQL做的不好
4. 全文索引
- 查找文本关键字,非比较索引键值
- 类似搜索引擎
- 相同列创建全文索引和B-Tree索引,不冲突
5. 其他索引
第三方引擎TokuDB
二. 索引好处
1. 好处
1) 减少扫描数据量
2) 避免排序和临时表
3) 随机IO转为顺序IO
2. 索引三星评价
评价索引是否适合某查询
第一星
索引将相关data行放到一起
第二星
索引的data行按查询所需顺序排序
第三星
索引含 查询全部列
三 .高性能索引策略
1. 独立的列
独立
索引列非表达式子式,或函数参数
两个错误:
1)索引列为表达式
select id from actor
where id + 1 = 5
2)
select ...
where
TO_DAYS(Current_DATE) - TO_DAYS(date_col) <= 10;
2. 前缀索引和索引选择性
1) 前缀索引
很长字符串,可索引开始的部分字符串
适用场景
BLOB,TEXT,很长的VARCHAR列
2) 优缺点
优点
节约索引空间
缺点
无法使用之做order by,Group by
无法使用做覆盖索引
3) 索引选择性
=不重复索引值/数据表记录总数
- 不重复索引值<-->基数<-->cardinality
- 记录总数<-->#T
- 取值范围 [1/#T ,1]
- 越高越好
选择性越高,过滤掉的行越多
4) 如何找到 前缀索引长度
思想
足够长(接近完整列),又不能太长(节约空间)
方法1 试验法
先算完整列频次,然后一个一个前缀试验
计算完整列频次
试验前3前缀
方法2 计算完整列选择性
使前缀选择性接近完整列选择性
5) 如何创建前缀索引
ALTER TABLE sakila
ADD KEY(city(7));
KEY(city(7))
3. 多列索引
1) 常见错误
每个列都创建单独索引,导致索引合并
create table t(
c1 int,
c2 int,
KEY(c1),
KEY(c2)
);
2) 索引合并表示索引建的不好,待优化
- 多个索引相交(AND)不如组合索引好
- 多个索引联合(OR)耗费CPU和内存资源
- 优化器不计算(耗费CPU和内存资源)到查询成本中
4. 选择合适的索引列顺序
仅适用于BTree索引(按顺序存储数据)
Btree索引按从左到右顺序,依次扫描
索引可按升、降序扫描,满足Order by,Group by,Distinct
如何选择合适的索引列顺序
经验法则
无order by和Group by时,选择性最高的列放在前面
select * from payment
where staff_id=2 and customer_id=584;
key(staff_id,customer_id)还是key(customer_id,staff_id)?
5. 聚簇索引(clustered index)
InnoDB支持,MyISAM为非聚簇
聚簇
数据行,键值存储在一起
一个表只能有一个聚簇索引
聚簇特点
- InnoDB通过主键聚集数据
主键未定义,用唯一非空索引聚集
无唯一非空索引,则隐式定义主键
- 只聚集同一页面记录
聚簇优点
- 相关数据保存在一起,如电子邮件(用户ID和全部邮件)
- 数据访问更快(索引和数据都在BTree中)
- 覆盖索引查询直接取页节点键值
聚簇缺点
数据全放内存时无优势(访问顺序不再重要)
插入速度依赖于插入顺序
InnoDB按主键顺序插入最快(否则插入后用optimize table优化表)
更新聚簇索引列代价很高
强制将每个更新行移动到新位置
页分裂问题
插入新行或,主键更新导致需移动行时
全表扫描慢
二级索引需两次索引查找
二级索引(secondary index,辅助索引)
叶节点保存行主键值,非指向data行的物理记录的指针
二级索引查找行步骤
- 叶子节点找到主键值
- 在聚簇索引找数据行
1 . InnoDB和MyISAM数据分布对比
InnoDB数据分布
InnoDB就是表,不用再像Myisam用单独列存储
聚簇索引叶子节点包含:
主键值
事物ID
回滚指针(用于事物和MVCC)
其他剩余列
聚簇和非聚簇表对比
2. InnoDB表按主键顺序插入行
无数据聚集,使用AUTO INCREMENT作为主键--保证按顺序写入
避免使用UUID(universal unique identifier)聚簇索引--导致插入变得随机
6. 覆盖索引
索引直接包含所需查询数据行,不需要回记录表(数据表)
只能用BTree做覆盖索引
支持InnoDB,myisam
Explain显示 Extra:Using index
覆盖索引优点
- 索引条目小于数据行,减少了数据访问量
- 范围查询IO少(索引列值顺序存储)
- 对InnoDB表(聚簇索引)特别有用
二级主键能覆盖查询可避免对主键索引的二次查询
MyISAM覆盖索引可能会导致系统问题
MyISAM引擎内存只缓存索引,数据由OS缓存
ICP索引条件推送(index condition pushdown)
MySQL5.6开始支持
条件过滤推到存储引擎层完成,减少IO访问
7. 用索引扫描做排序
MySQL生成有序结果的两种方式
- 排序
- 按顺序扫描索引
Exlain Type:Using index
为何索引扫描比全表扫描慢?
如果索引不能覆盖查询全部列,则每扫一条索引记录必须回表(随机IO)
同一索引,既满足排序,又满足查找是最好的
何时能用索引进行排序?
- 索引列序和order by顺序一致时
- 且所有列排序方向一样
不能使用索引进行排序的场景
- order by出现不同排序方向
- order by引用非索引列
- where和order by中的列无法组合为最左前缀
- where第一列是范围条件
- where出现IN(多个相等条件视为范围)
8. 压缩(前缀压缩)索引
MyISAM使用
减少索引大小(1/10磁盘空间)让更多索引进入内存
默认只压缩字符串,也可设置整数
只能从头开始扫描,无法二分
随机扫描导致适用于IO密集型(OLTP),不适用CPU密集型(OLAP)?
index1:perform
index2:performance-->7,ance
9. 冗余和重复索引
应删除重复索引
1) 重复索引
相同列创建多个索引
三个重复索引--unique,primary限制均通过索引实现
2) 冗余索引
应该删除冗余索引
两种冗余
已有key(A,B),再建key(A)
ID为主键,扩展索引为(A,ID)
建议
尽量扩展现有索引,而不是创建新索引,那样会导致冗余索引
10.删除未使用的索引
percona Toolkit--
pt-index-usage工具
11. 索引和锁
InnoDB存储引擎层完成条件过滤时(ICP--MySQL 5.6及以后),索引可减少访问行数,从而减少加锁数量
否则全表扫描并锁住所有行
覆盖索引失效:
- InnoDB二级索引上用共享(读)锁,访问主键索引需要排他(写)锁
- select for update比lock in share mode或非锁定查询慢
四. 索引和表维护
维护表三目的
找到并修复损坏的表
维护准确的索引统计信息
减少碎片
1. 找到并修复表
1) MyISAM表
check table--检查表
repair table--修复损坏的表
2) InnoDB表使用no-op ALTER
Alter TABLE innodb_tb ENGINE=INNODB;
2. 维护索引统计信息
优化器有时用索引统计信息估算扫描行数
ANALYZE TABLE更新统计信息避免错误
memory引擎不存储统计信息
MyISAM引擎存储统计信息在磁盘
Show Index from table查看索引基数(cardinality,索引列不同取值个数)
触发索引统计信息更新的三种情形
SHOW TABLE STATUS
SHOW INDEX
打开某些INFORMATION_SCHEMA表
3.减少索引和数据碎片
1)BTree索引会碎片化,降低查询效率
BTree随机访问是必须的,因为从root节点随机磁盘访问才能定位到叶子节点
2)三种数据碎片
行碎片
数据行存储在多个地方多个碎片中
行间碎片
逻辑上顺序的页或行,在磁盘上非顺序存储
剩余空间碎片
数据页中有大量不用的空余空间
MyISAM三种碎片都有,InnoDB无小碎片
3)如何消除碎片?
- OPTIMIZE TABLE
- ALTER TABLE tb ENGINE=;
- 删除所有索引-->重建表 -->重建索引
五. 总结
索引三原则
1.单行访问很慢
最好一个数据块读取多行
2. 按顺序访问范围行很快
- 顺序IO无需多次磁盘寻道,比随机IO快很多
- 服务器按顺序读取数据,则不需要额外排序
3. 索引覆盖查询很快
避免了大量单行访问
高性能MySQL--索引学习笔记(原创)的更多相关文章
- 《高性能MySQL》学习笔记
第1章 MySQL架构与历史 1.2 并发控制 MySQL在两个层面实现并发控制:服务器层与存储引擎层. 读锁和写锁: 在处理并发读或写时,可以通过实现一个由两种锁组成的系统来解决问题. 这两种锁通常 ...
- Mysql索引学习笔记
1.btree索引与hash索引 下列范围查询适用于 btree索引和hash索引: SELECT * FROM t1 WHERE key_col = 1 OR key_col IN (15,18,2 ...
- Mysql数据库学习笔记之数据库索引(index)
什么是索引: SQL索引有两种,聚集索引和非聚集索引,索引主要目的是提高了SQL Server系统的性能,加快数据的查询速度与减少系统的响应时间. 聚集索引:该索引中键值的逻辑顺序决定了表中相应行的物 ...
- 《高性能MySQL》读书笔记--锁、事务、隔离级别 转
1.锁 为什么需要锁?因为数据库要解决并发控制问题.在同一时刻,可能会有多个客户端对表中同一行记录进行操作,比如有的在读取该行数据,其他的尝试去删除它.为了保证数据的一致性,数据库就要对这种并发操作进 ...
- MySQL数据库学习笔记(九)----JDBC的ResultSet接口(查询操作)、PreparedStatement接口重构增删改查(含SQL注入的解释)
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- 基于【 MySql 】二 || mysql详细学习笔记
mysql重点学习笔记 /* Windows服务 */ -- 启动MySQL net start mysql -- 创建Windows服务 sc create mysql binPath= mysql ...
- Mysql事务学习笔记
Mysql事务学习笔记 1.事务概述 事务是数据库的执行单元,它包含了一条或多条sql语句,进行的操作是要么全部执行,要么全部都不执行. 2.事务执行命令 语法格式: start transactio ...
- MySQL数据库学习笔记(十二)----开源工具DbUtils的使用(数据库的增删改查)
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- MySQL数据库学习笔记(十)----JDBC事务处理、封装JDBC工具类
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- MYSQL数据库学习笔记1
MYSQL数据库学习笔记1 数据库概念 关系数据库 常见数据库软件 SQL SQL的概念 SQL语言分类 数据库操作 创建数据库 查看数据库的定义 删除数据库 修改数据库 创建表 数据类型 约束 ...
随机推荐
- 每天一个Linux命令(16)--which命令
把昨天的,留给昨天:今日,你将重新开始. 好的,在第一个阶段我们学习了 文件目录的操作命令: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ls cd pwd mkdir ...
- gulp快速入门&初体验
前言 一句话先 gulp 是一个可以简单和自动化"管理"前端文件的构建工具 先说我以前的主要工作,我主要是做游戏服务端的,用c++/python,所以我对东西的概念理解难免要套到自 ...
- dll
dll可以有一个入口点函数,系统会在不同的时候调用这个入口函数.这个调用是通知性质的,通常被dll用来执行一些与进程或线程有关的初始化和清理工作如果将dll的入口点函数命名为DllMain之外的其他名 ...
- AndroidStudio运行项目出现Unsupported method: AndroidProject.getPluginGeneration()错误解决办法
一.错误描述 今天在使用AndroidStudio运行项目时出现了一个Unsupported method: AndroidProject.getPluginGeneration()错误,如下图所示: ...
- lab1-Junit&Eclemma
Software Testing, Lab 1 March 10. 2016, by 赵国佺(3014218108) 一. environment setup Firstly, I downl ...
- wemall app商城源码中基于JAVA通过Http请求获取json字符串的代码
wemall-mobile是基于WeMall的Android app商城,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可定制修改.分享其中关于通过Http请求获取json字符串的代码供 ...
- 1578: [Usaco2009 Feb]Stock Market 股票市场
1578: [Usaco2009 Feb]Stock Market 股票市场 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 414 Solved: 1 ...
- 1620: [Usaco2008 Nov]Time Management 时间管理
1620: [Usaco2008 Nov]Time Management 时间管理 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 506 Solved: ...
- 关于vue-clidown到本地后,拷贝文件库到另外一台电脑上npm run dev编译报错的处理
这些天自己在用vue-cli项目,在家里的电脑下下来后写了一些demo,拿到公司继续开发的时候发现删除node_modules文件,运行npm install和npm run 百度,搜狗了好久都没有找 ...
- Android Weekly Notes Issue #248
Android Weekly Issue #248 March 5th, 2017 Android Weekly Issue #248. 本期内容包括: 为什么有时候应该让你的应用崩溃(而不是一味保护 ...