create 创建索引时必须指定索引名alter table 创建索引时可不指定索引名
-- 唯一索引: 在table_name 表中col_name 字段添加唯一索引index_name
create unique index index_name
on table_name (col_name [(length)] [asc / desc])
-- 主键索引: 在table_name 表中col_name 列添加主键索引
alter table table_name add primary key (col_name)
/*
主键索引 和 唯一索引 在指定字段约束时默认为索引,
或建表之后使用以上方式添加
*/
-- 普通索引 (所有索引都可用这两种创建方式)
-- 方式1
create index index_name on tab_name (col_name [(length)] [asc / desc])
-- 方式2
alter table `table_name` add index [index_name](index_col_name)
-- 在table_name 表中删除 index_name 索引
drop index index_name on table_name
-- 删除主键索引
-- 从table_name表中删除主键索引
alter table `table_name` drop primary key
show index from table_name; -- 方式1
show indexes from table_name; -- 方式2
show keys from table_name; -- 方式3
desc table_name; -- 方式4,在表结构中看索引,但没有前三种索引信息详细
# 查询表的索引
show indexes from table_name; -- 查询表 table_name 中所有索引
字段定义为主键后自动为主键索引(类型 primary key)
字段值唯一且不允许为空
id int primary key , -- 主键约束,自动为主键索引
字段定义为 unique 后自动为唯一索引
字段值唯一,允许为 null
card_id int unique , -- 唯一约束,自动为唯一索引
最左匹配原则
where 子句中使用最频繁的一列放在最左边
name 经常作为查询条件,salary 不常使用
name 放在联合索引的第一位置,即最左边alert table emp add index name_salary (name,salary);select * from emp where name = '';
select * from where salary = xxx;
slect * from emp where name = '' and salary = xxx;
selct * from emp where salary = xxx and name = '';
MySQL 执行SQL时会进行优化,底层进行颠倒优化多字段联合添加索引
单列索引:节点中关键字[name] 及索引的关键字的值为那么对应的值,比如 张三。
联合索引:节点中关键字[name,phoneNum],比如张三,138888888。
联合索引列选择原则
创建联合索引的时,如:(k1,k2,k3)
相当于创建(k1)、(k1,k2)和(k1,k2,k3)三个索引,这就是最左匹配原则。
联合索引不满足最左原则,索引一般会失效
索引下推:select * from table where name = ? and age = ?
MySQL5.6 及以后的版本出现
原查询过程:先根据 name 在存储引擎中获取数据,后根据 age 在 server 层过滤
有索引下推后:根据 name、age 在存储引擎获取数据,返回对应的数据,不再到 server 层过滤
使用 Explain 分析SQL语句时出现 index condition pushdown 就是使用了索引下推
单一字段添加索引
同时存在联合索引和单列索引(字段有重复)
涉及到 MySQL 本身的查询优化器策略
mysql 根据查询语句的成本来选择使用哪条索引MySQL 执行优化器会对其进行优化
where 条件顺序对效率没有影响,真正有影响的是是否用到了索引!MATCH AGAINST,而不是普通的 WHEREfulltext
Solr 和 ElasticSearch(ES)InnoDB 会选择一个唯一的非空索引代替
InnoDB 会隐式定义一个主键作为聚簇索引InnoDB 只聚集在同一个页面中的记录,包含相邻键值的页面可能相距甚远InnoDB 使用聚簇索引将主键组织到一棵B+树中,行数据就储存在叶子节点
where id = 14 条件查找主键,按照B+树的检索算法即可查找到对应的叶节点,获得行数据Name 列进行条件搜索需要两个步骤
MyISAM 使用非聚簇索引
辅助索引:InnoDB 中在聚簇索引上创建的索引
InnoDB 移动行时无须更新辅助索引中的指针
OPTIMIZE TABLE 优化表
将数据存储与索引分开结构
MyISAM 通过 key_buffer 把索引先缓存到内存中
使用聚簇索引和非聚簇索引

回表:从非聚簇索引跳转到聚簇索引中查找数据
select id, name, age from table where name = 'kaka';
MySQL 常用两种索引结构(算法)
Hash 索引的底层由 Hash 表实现的
BTree 比 Hash 多:Hash 本身由于其特殊性,带来了很多限制和弊端
Hash 索引仅能满足 =、IN、<=> 查询,不能使用范围查询Hash 索引不能利用部分索引键查询
Hash 要么全部使用,要么全部不使用,不支持 BTree 支持的联合索引的最优前缀Hash 索引无法避免数据的排序操作
Hash 索引中存放的是经过 Hash 计算后的值Hash 运算前的键值完全一样
Hash 索引任何时候都不能避免表扫描
Hash 索引将索引键运算后,运算结果和所对应的行指针信息存放于 Hash 表中Hash 值
Hash 键值的数据的记录条数,也无法从Hash索引中直接完成查询Hash 值相等的情况后性能并不一定比 BTree 高InnoDB 存储引擎有特殊的功能:自适应哈希索引
相对平衡二叉树:BTree
多路平衡查找树:B-Tree
m 阶的 B 树要求除根节点以外,所有的非叶子子节点必须要有 [m/2,m] 个子树
加强版多路平衡查找树:B+Tree;B-Tree plus 版

基于 BTree 和叶子节点顺序访问指针进行实现
BTree 的平衡性,且通过顺序访问指针来提高区间查询的性能用于查找,还可以用于排序和分组。
可指定多个列作为索引列,多个索引列共同组成键
适用于全键值、键值范围和键前缀查找
InnoDB 的 B+Tree 索引分为主索引和辅助索引
B+Tree 中一个节点的 key 从左到右非递减排列
某个指针的左右相邻 key 分别是 keyi 和 keyi+1,且不为 null
该指针指向节点的所有 key >= keyi 且 <= keyi+1
查找
在根节点进行二分查找,找到一个 key 所在的指针
递归地在指针所指向的节点进行查找。直到查找到叶子节点
在叶子节点上进行二分查找,找出 key 所对应的 data
B+Tree 与 B-Tree 的区别
B+ 节点关键字搜索采用闭合区间
B+ 非叶节点不保存数据相关信息,只保存关键字和子节点的引用。B+ 关键字对应的数据保存在叶子节点中B+ 叶子节点是顺序排列的,且相邻节点具有顺序引用的关系为什么选择 B+Tree ?
select 查询默认全表扫描,找到所有符合条件的记录
数据结构:B + tree
执行流程
检索时首先查看条件字段是否有索引
有索引对象时通过索引检索
通过索引定位数据
原 select 语句转为 select ... where 物理地址 = 检索到的物理地址
例如:select ename from emp where ename = 'SMITH';
查看 ename 字段,发现该字段有索引
通过 ename 字段索引对象检索
索引已经对字段进行了排序
减少扫描次数,快速定位数据
查找到记录的物理地址 假如:0x00011
sql 语句变形为 select ... where 物理地址 = 0x00011优、劣
优点:优化查询速度
缺点
数据量庞大
较频繁作为查询条件的字段应创建索引
唯一性太差的字段不适合单独创建索引
DML 操作非常频繁的字段不适合创建索引
不会出现在 where 字句的字段不应该创建索引
like 子查询,% 放前面
非空判断 is not null
or 语句前后没有同时使用索引
数据类型出现隐式转化
varchar 不加单引号的话可能会自动转换为int型,使索引无效,产生全表扫描BLOB、TEXT 和 VARCHAR 类型字段使用前缀索引,只索引开始的部分字符。
InnoDB 引擎,若辅助索引能够覆盖查询,则无需访问主索引
create index name_phoneNum on users(name,phoneNum)
select name, phoneNum from ... ; 使用覆盖索引