MYSQL 索引(一)--- 简介
简介
Mysql 官方定义 : 索引(Index) 是帮助 Mysql 高效获取数据的数据结构。
索引的目的在于提交查询效率,可以类比字典。简单理解为 “排好序的快读查找数据结构”。
数据本身之外,数据库还维护着一个满足特定查找算法的数据结构哦,这些数据结构以某种方式指向数据,这样就可以在这些数据结构的基础上实现高级查找算法。这种数据结构就是索引。
一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储在在盘上。
优劣
优势:
- 提高了数据检索效率,降低数据库的 IO 成本
- 通过索引对数据进行排序,降低数据排序的成本,降低了 CPU 的消耗
劣势:
- 实际上索引也是一张表,该表保存了主键和索引字段,并指向实体表的记录,所以索引列也要占用空间
- 索引大大提高了查询速度,同时会降低更新表的速度。因为更新表时不仅要保存数据,还要保存索引文件每次更新添加了索引列的字段。
索引分类
- 单值索引:即一个索引只包含单个列,一个表可以有多个单值索引
- 唯一索引:索引列的值必须唯一,但允许有空值
- 复合索引:一个索引包含单个列
基本语法
# 创建 如果是 CHAR,VARCHAR 类型,length可以小于字段实际长度,如果是 BLOB和TEXT类型,必须指定 length
CREATE [UNIQUE] INDEX index_name ON table_name(columnname(length));
# 或
ALTER table_name ADD [UNIQUE] INDEX [index_name] ON (column(length))
#删除
DROP INDEX [index_name] ON table_name
#查看
SHOW INDEX FREOM table_name\G
索引建立情况
- 主键自动建立唯一索引
- 频繁作为查询条件的字段应该创建索引
- 查询中与其他表关联的字段,外键关系应该创建索引
- 频更新的字段不适合做索引
- Where 条件中用不到的字段不适合创建索引
- 单键/组合键索引的选择问题(高并发下倾向创建组合索引)
- 查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度
- 查询中统计或者分组的字段
不创建索引情况
- 表记录太少
- 经常增删改的表
- 数据重复且分布平均的表字段,应该只为最经常查询和排序的字段建立索引
Explain
查看执行计划: explain + SQL
- 表的读取速度
- 数据读取操作的操作类型
- 那些索引可以使用
- 那些索引被实际使用
- 表之间的引用
- 每张表有多少行被优化器查询
id
id : select 查询的序列号,包含一组数字,表示查询中执行 select 子句或操作表的顺序
- id 相同 : 执行顺序由上至下
- id不同 :如果是子查询,id 的序号会递增,id 值越大优先级越高,越先被执行
- id 有相同又有不同的 ,同时存在
select_type
查询类型 | 含义 |
---|---|
SIMPLE | 简单的 select 查询,不包含子查询或者 UNION |
PRIMARY | 查询中包含任何复杂的子部分,最外层查询则被标准为 PRIMARY |
SUBQUERY | 在 SELECT 或 WHERE 列表中包含了子查询 |
DERIVED | 在 FROM 列表中包含的子查询被标记为 DERIVED(衍生) ,MYSQL 会递归执行这些子查询,把结果放在临时表里 |
UNION | 若第二个 SELECT 出现在 UNION 之后,则被标记为 UNION;若 UNION 包含在 FROM 子句的子查询中,外层 SELECT将被标记为:DERIVED |
UNION RESULT | 从 UNION 表获取结果的 SELECT |
table
显示这一行数据是关于哪张表
type
type: 显示查询使用了哪种查询类型。常见查询类型如下:
ALL | index | range | ref | eq_ref | const, system | NULL |
---|
从最好到最差依次是:
system > const > eq_ref > ref > range > index > ALL
访问类型 | 含义 |
---|---|
system | 表只有一行记录(等于系统表),这是 const 类型的特例,平时不会出现,可以忽略不计 |
const | 表示通过索引一次就找到了, const 用于比较 primary或者 unique索引。因为只匹配到一行数据,所以很快。如将主键置于 where 列表中, Mysql 就能将该查询转换为一个常量 |
eq_ref | 唯一性索引扫描,对于每个索引建,表中只有一行数据与之匹配。常见于主键或唯一性索引扫描 |
ref | 非唯一性索引扫描,返回匹配某个单独值的所有航,本质上也是一种索引访问,它返回所有匹配某个单独值的行。然而,它可能会找到多个符合条件的行,所以他应该是属于查找和扫描的混合体 |
range | 只检索非定范围的行,使用一个索引来选择行。key 列显示使用了那个索引。 一般就是在你的 where 语句中出现了 between、<、>、in 等的查询。这种范围扫描索引扫描比全表扫描要好,因为他只需要开始于索引的某一点,而结束语另一点,不用扫描全部索引 |
index | Full Index Scan,index 与 ALL 区别为 index 类型只遍历索引树。这通常比 ALL 快,因为索引文件通常比数据文件小。(虽然 all 和 index 都是读全表,但 index是从索引中读出,而 all 是从硬盘中读的) |
all | Full Table Scan,将遍历全表以找到匹配的行 |
possible_keys
显示可能应用到这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。
key
实际使用的索引。如果为 NULL,则没有使用索引。
查询中若使用了覆盖索引,则该索引仅出现在 key 列表中。
key_len
表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。在不损失精确性的情况下,长度越短越好。 key_len 显示的值为索引字段的最大可能长度,并非实际长度,即 key_len 是根据表定义计算而得,并不是通过表内检索出的。
ref
显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值
row
根据表统计信息及索引选用情况,大致估算出找到所需记录所需要读取的行数
extra
不适合在其他列中显示但十分重要的额外信息
信息 | 含义 |
---|---|
Using filesort | 说明 mysql 会对数据使用一个额外的索引排序,而不是按照表内的索引顺序进行读取。Mysql 中无法利用索引完成的排序操作称为“文件排序”。 |
Usering temporary | 使用了临时表保存中间结果,Mysql 在对查询结果排序时使用临时表,常见于排序 order by 和分组查询 group by |
Using index | 表示相应的 select 操作中使用了覆盖索引,避免访问了表的数据行,效率不错。如果同时出现 using where ,表明索引被用来执行索引键值的查找。如果没有同时出现 using where,表明索引用来读取数据而非执行查找动作。Covering Index 覆盖索引。理解方式一 : select 的数据列只用从索引中就能够取得,不必读取数据行, Mysql 可以利用索引返回 select 列表中的字段,而不必根据索引再次读取数据文件,换句话说查询列要被所建的索引覆盖。理解方式二 : 索引是高校找到行的一个方法,但是一般数据库也能使用索引找到一个列的数据。因此它不必读取整个行,毕竟索引叶子节点存储了他们索引的数据;当能通过都区索引就可以得到想要的数据,那就不需要读取行了。一个索引包含(或覆盖)了满足查询结果的数据就叫做覆盖索引 。 |
using where | 表示使用了 where 过滤 |
using join buffer | 使用了连接缓存 |
impossible where | where 子句的值总是 false,不能用来获取任何元组 |
select tables optimized away | 在没有 group by 子句的情况下,基于索引优化 MIN/MAX 操作或者对于 MyISAM 存储引擎优化 COUNT(*) 操作,不必等到执行阶段在进行计算,查询执行计划生成的阶段即完成优化 |
distinct | 优化 distinct 操作,在中到第一匹配的元组后即停止找同样值的动作 |
使用情况
- 观察,至少跑一天,看看生产的慢 SQL 情况
- 开启慢查询日志,设置阈值,比如超过 5 秒的就是慢 SQL,并把他们抓取出来
- explain + 慢 SQL 分析
- show profile : 查询 SQL 在 Mysql 服务器里面的执行细节和生命周期情况
- 运维经理或DBA,进行 SQL 数据库服务器参数调优
你一定会喜欢那个因为喜欢她而发光的自己!
个人博客:http://www.yanghelong.top
个人博客:http://www.yanghelong.top