mysql索引

一. 增删索引

https://www.cnblogs.com/zz-tt/p/6609828.html

1. 索引分类

  1. 主键索引(PROMARY KEY): 不能重复。id 不能是null
  2. 唯一索引(UNIQUE) :不能重复。id 可以是null
  3. 单值索引(INDEX) : 单列, age ;一个表可以多个单值索引,name。
  4. 复合索引 :多个列构成的索引 (相当于 二级目录 : z: zhao) (name,age) (a,b,c,d,…,n)



二. 创建索引

a. 使用ALTER TABLE语句创建索性(用这个)

介绍:应用于表创建完毕之后再添加。
格式:alter table 表名 add 索引类型 索引名(字段)

  1. 普通索引
    alter table table_name add index index_name (column_list) ;
  2. 唯一索引(unique)
    alter table table_name add unique (column_list) ; //这里就是缺省index_name
  3. 主键索引
    alter table table_name add primary key (column_list) ;
  4. 组合索引:多个字段放一起就是组合索引
    alter table table_name add index index_name ( column1, column2, column3 )

总结:

  • alter table可用于创建普通索引UNIQUE索引PRIMARY KEY索引3种索引格式.
  • table_name:要增加索引的表名;column_list:指出对哪些列进行索引;多列时各列之间用逗号分隔。
  • 索引名index_name可选填,缺省时,MySQL将根据第一个索引列赋一个名称。
  • alter table允许在单个语句中更改多个表,因此可以同时创建多个索引。

b. 使用CREATE INDEX语句对表增加索引

介绍:create index可用于对表增加普通索引或UNIQUE索引,可用于建表时创建索引
格式:create 索引类型 索引名 on 表(字段)
注意:如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length。

  1. 普通索引
    create index index_name on table_name (column_list)
  2. 唯一索引(UNIQUE)
    create unique index index_name ontable_name (column_list)
  3. 复合索引
    create index dept_name_index on tb(column1,column2);

总结:

  • table_name、index_name和column_list具有与alter table语句中相同的含义,索引名不可选。
  • 不能用create index语句创建primart key索引。(不能创建主键索引

c. 区别
  1. create index必须提供索引名,对于ALTER TABLE,将会自动创建,如果你不提供;
  2. create index一个语句一次只能建立一个索引,ALTER TABLE可以在一个语句建立多个,如:
    alter table HeadOfState addprimary key (ID), add index (LastName,FirstName);
  3. 只有alter table 才能创建主键



三. 删除索引

介绍:两种删除方式—> alter table 和 drop index 。drop index 可以在 alter table 内部作为一条语句处理

  1. //删除普通索引(drop index)(用这个)
    drop index index_name on table_name ;
  2. //删除普通索引(alter table)
    alter table table_name drop index index_name ;
  3. //删除主键索引
    alter table table_name drop primary key ;

注意:

  • 其中,在前面的两条语句中,都删除了table_name中的索引index_name。而在最后一条语句中,只在删除PRIMARY KEY索引中使用,因为一个表只可能有一个PRIMARY KEY索引,因此不需要指定索引名。如果没有创建PRIMARY KEY索引,但表具有一个或多个UNIQUE索引,则MySQL将删除第一个UNIQUE索引。
  • 如果从表中删除某列,则索引会受影响。对于多列组合的索引,如果删除其中的某列,则该列也会从索引中删除。如果删除组成索引的所有列,则整个索引将被删除。



四. 查询索引

介绍:查询当前表有哪几个索引
show index from 表名 ;
show index from 表名 \G



五 SQL执行过程

编写过程:

  • select dinstinct …from …join …on …where …group by …having …order by …limit …

解析过程:

  • from … on… join …where …group by …having …select dinstinct …order by limit …



六. explain 关键字

https://www.cnblogs.com/gomysql/p/3720123.html
id : 执行编号
select_type :查询类型
table :表
type :类型
possible_keys :预测用到的索引
key :实际使用的索引
key_len :实际使用索引的长度
ref :表之间的引用
rows :通过索引查询到的数据量
Extra :额外的信息

1. id:包含一组数字,表示查询中执行select子句或操作表的顺序

三种情况:

  1. id相同,执行顺序由上至下
  2. 如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行
  3. id如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id值越大,优先级越高,越先执行

2. select_type:查询中每个select子句的类型(简单OR复杂)
  1. SIMPLE:查询中不包含子查询或者UNION
  2. PRIMARY:查询中若包含任何复杂的子部分,最外层查询则被标记为PRIMARY
  3. SUBQUERY:在SELECT或WHERE列表中包含了子查询,该子查询被标记为SUBQUERY
  4. DERIVED:在FROM列表中包含的子查询被标记为:DERIVED(衍生)用来表示包含在from子句中的子查询的select,mysql会递归执行并将结果放到一个临时表中。服务器内部称为"派生表",因为该临时表是从子查询中派生出来的
  5. UNION:若第二个SELECT出现在UNION之后,则被标记为UNION;若UNION包含在FROM子句的子查询中,外层SELECT将被标记为:DERIVED
  6. UNION RESULT :从UNION表获取结果的SELECT被标记为UNION RESULT

注意:SUBQUERY(3)和UNION(5)还可以被标记为DEPENDENT和UNCACHEABLE。
DEPENDENT意味着select依赖于外层查询中发现的数据。
UNCACHEABLE意味着select中的某些 特性阻止结果被缓存于一个item_cache中。


3. type:表示MySQL在表中找到所需行的方式,又称“访问类型”

https://www.cnblogs.com/gomysql/p/3720123.html
依次从好到差: ALL, index, range, ref, eq_ref, const, system, NULL
注意:

  1. system,const,index , range,index_merge,ALL 单独查询
  2. eq_ref,ref,ref_or_null, all 多表join 查询
  3. index_subquery , unique_subquery 子查询
  4. system/const: 结果只有一条数据
  5. eq_ref:结果多条;但是每条数据是唯一的 ;
  6. ref:结果多条;但是每条数据是是0或多条 ;
  7. system,const只是理想情况;实际能达到 ref>range
  8. 要对type进行优化的前提:有索引

4. possible_keys:可能用到的索引,是一种预测,不准。

5. key:显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL

6. key_len:表示索引中使用的字节数

作用:用于判断复合索引是否被完全使用()
规则:

  1. 如果索引字段可以为Null,则会使用1个字节用于标识。
  2. 在utf8:1个字符站3个字节
  3. 用2个字节 标识可变长度(varchar就是可变长度类型)

计算:varchar(20) 如果为索引且可以为空
结果: 20*3=60 + 1(null) +2(用2个字节 标识可变长度) =63;最终索引长度为63


7. ref:表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值

注意: 注意与type中的ref值区分。


8. rows:被索引优化查询的 数据个数 (实际通过索引而查询到的 数据个数)

9. Extra:包含不适合在其他列中显示但十分重要的额外信息
  1. Using index
    性能提升;该值表示相应的select操作中使用了覆盖索引(Covering Index)

  2. Using where
    表示mysql服务器将在存储引擎检索行后再进行过滤。许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带where字句的查询都会显示"Using where"。有时"Using where"的出现就是一个暗示:查询可受益与不同的索引。

  3. Using temporary
    性能损耗大,表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询
    这个值表示使用了内部临时(基于内存的)表。一个查询可能用到多个临时表。有很多原因都会导致MySQL在执行查询期间创建临时表。两个常见的原因是在来自不同表的上使用了DISTINCT,或者使用了不同的ORDER BY和GROUP BY列。可以强制指定一个临时表使用基于磁盘的MyISAM存储引擎。这样做的原因主要有两个:
              a. 内部临时表占用的空间超过min(tmp_table_size,max_heap_table_size)系统变量的限制
              b. 使用了TEXT/BLOB 列

  4. Using filesort
    性能消耗大;MySQL中无法利用索引完成的排序操作称为“文件排序”

  5. Impossible where
    这个值强调了where语句会导致没有符合条件的行。(where子句永远为false)



七、索引的使用及注意事项

SELECT `sname` FROM `stu` WHERE `age`+10=30;-- 不会使用索引,因为所有索引列参与了计算

SELECT `sname` FROM `stu` WHERE LEFT(`date`,4) <1990; -- 不会使用索引,因为使用了函数运算,原理与上面相同

SELECT * FROM `houdunwang` WHERE `uname` LIKE'后盾%' -- 走索引

SELECT * FROM `houdunwang` WHERE `uname` LIKE "%后盾%" -- 不走索引

-- 正则表达式不使用索引,这应该很好理解,所以为什么在SQL中很难看到regexp关键字的原因

-- 字符串与数字比较不使用索引;
CREATE TABLE `a` (`a` char(10));
EXPLAIN SELECT * FROM `a` WHERE `a`="1" -- 走索引
EXPLAIN SELECT * FROM `a` WHERE `a`=1 -- 不走索引

select * from dept where dname='xxx' or loc='xx' or deptno=45 --如果条件中有or,即使其中有条件带索引也不会使用。换言之,就是要求使用的所有字段,都必须建立索引, 我们建议大家尽量避免使用or 关键字

-- 如果mysql估计使用全表扫描要比使用索引快,则不使用索引

使用索引时,有一些技巧:

  1. 索引不会包含有NULL的列

    只要列中包含有NULL值,都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此符合索引就是无效的。

  2. 使用短索引

    对串列进行索引,如果可以就应该指定一个前缀长度。例如,如果有一个char(255)的列,如果在前10个或20个字符内,多数值是唯一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

  3. 索引列排序

    mysql查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作,尽量不要包含多个列的排序,如果需要最好给这些列建复合索引。

  4. like语句操作
    一般情况下不鼓励使用like操作,如果非使用不可,注意正确的使用方式。like ‘%aaa%’不会使用索引,而like ‘aaa%’可以使用索引。

  5. 不要在列上进行运算

  6. 不使用NOT IN 、<>、!=操作,但<,<=,=,>,>=,BETWEEN,IN是可以用到索引的(IN有时会失效)

  7. 索引要建立在经常进行select操作的字段上。

    这是因为,如果这些列很少用到,那么有无索引并不能明显改变查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。

  8. 索引要建立在值比较唯一的字段上。

  9. 对于那些定义为text、image和bit数据类型的列不应该增加索引。因为这些列的数据量要么相当大,要么取值很少。

  10. 在where和join中出现的列需要建立索引。

  11. where的查询条件里有不等号(where column != …),mysql将无法使用索引。

  12. 如果where字句的查询条件里使用了函数(如:where DAY(column)=…),mysql将无法使用索引。

  13. 在join操作中(需要从多个数据表提取数据时),mysql只有在主键和外键的数据类型相同时才能使用索引,否则及时建立了索引也不会使用。



八、优化

1. 单表优化总结:
  1. 最佳做前缀,保持索引的定义和使用的顺序一致性
  2. 索引需要逐步优化
  3. 将含In的范围查询 放到where条件的最后,防止失效。(iny有时候会使索引失效)
2. 两表优化总结:
  1. 小表驱动大表,即把大的数据放到后面,我们在for循环也应该把大的数据放到里面;
    当编写 where on t.cid=c.cid 时,将数据量小的表 放左边(假设此时t表数据量小)
  2. 索引建立经常使用的字段上;般情况对于左外连接,给左表加索引;右外连接,给右表加索引
3. 三表优化总结:
  1. 如果 (a,b,c,d)复合索引 和使用的顺序全部一致(且不跨列使用),则复合索引全部使用。如果部分一致(且不跨列使用),则使用部分索引。
    select a,c where a = and b= and d=         //只会使用a和b这个索引
  2. .where和order by 拼起来,不要跨列使用(即在where中使用a,b,索引的时候,在order by 中我们尽量使用c索引,保证不夸列使用)

你可能感兴趣的:(mysql索引)