有关普通索引和组合索引问题:

索引分单列索引和组合索引:单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引;组合索引,即一个索包含多个列。
  MySQL索引类型包括:
  (1)普通索引是最基本的索引,它没有任何限制。它有以下几种创建方式:
  ◆创建索引
    CREATE INDEX indexName ON mytable(username(length));
    如果是 CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length,下同。
  ◆修改表结构
    ALTER mytable ADD INDEX [indexName] ON (username(length))
  ◆ 创建表的时候直接指定
    CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, INDEX [indexName] (username(length)) );
  删除索引的语法:
    DROP INDEX [indexName] ON mytable;
  (2)唯一索引与普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:
  ◆创建索引
     CREATE UNIQUE INDEX indexName ON mytable(username(length))
  ◆修改表结构
    ALTER mytable ADD UNIQUE [indexName] ON (username(length))
  ◆创建表的时候直接指定
    CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, UNIQUE [indexName] (username(length)) );
  (3)主键索引是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引:
    CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, PRIMARY KEY(ID) );
  当然也可以用 ALTER 命令。记住:一个表只能有一个主键。
  (4)组合索引
    为了形象地对比单列索引和组合索引,为表添加多个字段:
    CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, city VARCHAR(50) NOT NULL, age INT NOT NULL );
  为了进一步榨取MySQL的效率,就要考虑建立组合索引。就是将 name, city, age建到一个索引里:
    ALTER TABLE mytable ADD INDEX name_city_age (name(10),city,age);
  建表时,usernname长度为 16,这里用 10。这是因为一般情况下名字的长度不会超过10,这样会加速索引查询速度,还会减少索引文件的大小,提高INSERT的更新速度。
  如果分别在 usernname,city,age上建立单列索引,让该表有3个单列索引,查询时和上述的组合索引效率也会大不一样,远远低于我们的组合索引。虽然此时有了三个索引,但MySQL只能用到其中的那个它认为似乎是最有效率的单列索引。
  建立这样的组合索引,其实是相当于分别建立了下面三组组合索引:
    usernname,city,age usernname,city usernname
  为什么没有 city,age这样的组合索引呢?这是因为MySQL组合索引“最左前缀”的结果。简单的理解就是只从最左面的开始组合。并不是只要包含这三列的查询都会用到该组合索引,下面的几个SQL就会用到这个组合索引:
    SELECT * FROM mytable WHREE username="admin" AND city="郑州"   SELECT * FROM mytable WHREE username="admin"
  而下面几个则不会用到:
    SELECT * FROM mytable WHREE age=20 AND city="郑州"   SELECT * FROM mytable WHREE city="郑州"
  (5)建立索引的时机
    到这里我们已经学会了建立索引,那么我们需要在什么情况下建立索引呢?一般来说,在WHERE和JOIN中出现的列需要建立索引,但也不完全如此,因为MySQL只对<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE才会使用索引。例如:
  SELECT t.Name FROM mytable t LEFT JOIN mytable m ON t.Name=m.username WHERE m.age=20 AND m.city='郑州'
  此时就需要对city和age建立索引,由于mytable表的 userame也出现在了JOIN子句中,也有对它建立索引的必要。
  刚才提到只有某些时候的LIKE才需建立索引。因为在以通配符%和_开头作查询时,MySQL不会使用索引。例如下句会使用索引:
    SELECT * FROM mytable WHERE username like'admin%'
  而下句就不会使用:
    SELECT * FROM mytable WHEREt Name like'%admin'
  因此,在使用LIKE时应注意以上的区别。
  (6)索引的不足之处
  上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:
    ◆虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行 INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。
    ◆建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快。
    索引只是提高效率的一个因素,如果你的 MySQL有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询语句。
  (7)使用索引的注意事项
  使用索引时,有以下一些技巧和注意事项:
    ◆索引不会包含有NULL值的列
  只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有 NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。
  ◆使用短索引
  对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。
  ◆索引列排序
  MySQL查询只使用一个索引,因此如果 where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。
  ◆like语句操作
  一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。
  ◆不要在列上进行运算
    select * from users where YEAR(adddate)<2007;
  将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成
     select * from users where adddate<‘2007-01-01’;
  ◆不使用NOT IN和<>操作

sql优化&执行计划:

禁用select *
使用select count(*) 统计行数
尽量少运算
尽量避免全表扫描,如果可以,在过滤列建立索引
尽量避免在where子句对字段进行null判断
尽量避免在where子句使用!= 或者<>
尽量避免在where子句使用or连接
尽量避免对字段进行表达式计算
尽量避免对字段进行函数操作
尽量避免使用不是复合索引的前缀列进行过滤连接
尽量少排序,如果可以,建立索引
尽量少join
尽量用join代替子查询
尽量避免在where子句中使用in,not in或者having,使用exists,not exists代替
尽量避免两端模糊匹配 like %***%
尽量用union all代替union
尽量早过滤
避免类型转换
尽量批量insert
优先优化高并发sql,而不是频率低的大sql
尽可能对每一条sql进行explain
尽可能从全局出发

SQL执行计划

在mysql命令行中,执行explain命令可以看到sql执行计划,如下图所示:

ID

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

id相同,可以认为是一组,执行顺序由上至下
如果是子查询,id的序号会递增
id值越大优先级越高,越先被执行

select_type

select_type:表示查询中每个select子句的类型(简单 、复杂)

SIMPLE:查询中不包含子查询或者UNION
PRIMARY:查询中若包含任何复杂的子部分,最外层查询则被标记为PRIMARY
SUBQUERY:在SELECT或WHERE列表中包含了子查询,该子查询被标记为SUBQUERY
DERIVED:在FROM列表中包含的子查询被标记为DERIVED(衍生)。若UNION包含在  FROM子句的子查询中,外层SELECT将被标记为DERIVED
UNION:若第二个SELECT出现在UNION之后,则被标记为UNION
UNION RESULT:从UNION表获取结果的SELECT被标记为UNION RESULT

table

输出的行所引用的表

type

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

ALL:Full Table Scan, MySQL将遍历全表以找到匹配的行
index:Full Index Scan,index与ALL区别为index类型只遍历索引树
range:索引范围扫描,对索引的扫描开始于某一点,返回匹配值域的行,常见于between、<、>等的查询
ref:非唯一性索引扫描,返回匹配某个单独值的所有行。常见于使用非唯一索引即唯一索引的非唯一前缀进行的查找
eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描
const、system:当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量。system是const类型的特例,当查询的表只有一行的情况下, 使用system
NULL:MySQL在优化过程中分解语句,执行时甚至不用访问表或索引

possible_keys

指出MySQL能使用哪个索引在表中找到行,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用。

key

显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL。查询中若使用了覆盖索引,则该索引仅出现在key列表中。

key_len

表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的。

row

表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数。

Extra

包含不适合在其他列中显示但十分重要的额外信息

Using index:该值表示相应的select操作中使用了覆盖索引(Covering Index)【注:MySQL可以利用索引返回select列表中的字段,而不必根据索引再次读取数据文件  包含所有满足查询需要的数据的索引称为 覆盖索引】
Using where:表示MySQL服务器在存储引擎受到记录后进行“后过滤”(Post-filter),如果查询未能使用索引,Using where的作用只是提醒我们MySQL将用where子句来过滤结果集
Using temporary:表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询
Using filesort:  MySQL中无法利用索引完成的排序操作称为“文件排序”

Mysql的普通索引复合索引执行优化相关推荐

  1. 【推荐】mysql联合 索引(复合索引)的探讨

    Mysql联合 索引(复合索引)的使用原则 命名规则:表名_字段名 需要加索引的字段,要在where条件中. 数据量少的字段不需要加索引.最窄的字段放在键的左边. 如果where条件中是OR关系,必须 ...

  2. MySQL 性能分析 之 联合索引(复合索引)实践分析

    MySQL 性能分析 之 联合索引(复合索引)实践分析 作为开发者,大家都知道,一个服务器.一个数据库的性能是项目的重中之重,后台架构.写法与数据库设计的好坏往往直接影响到整个项目的性能. 索引:是当 ...

  3. pandas索引复合索引dataframe数据、索引其中一个水平(level)的所有数据行(index all rows in a level)

    pandas索引复合索引dataframe数据.索引其中一个水平(level)的所有数据行(index all rows in a level) 目录

  4. pandas索引复合索引dataframe数据、索引dataframe中指定行和指定列交叉格子的数据内容(getting a specific value)、使用元组tuple表达复合索引的指定行

    pandas索引复合索引dataframe数据.索引dataframe中指定行和指定列交叉格子的数据内容(getting a specific value).使用元组tuple表达复合索引的指定行 目 ...

  5. pandas索引复合索引dataframe数据、索引其中一个水平(level)的所特定数据行、指定数据行(index a row of a level)、使用元组tuple表达复合索引的指定行

    pandas索引复合索引dataframe数据.索引其中一个水平(level)的所特定数据行.指定数据行(index a row of a level).使用元组tuple表达复合索引的指定行 目录

  6. pandas索引复合索引dataframe数据、索引其中多个水平(level)的多个数据行(index rows from different levels)、使用元组tuple表达复合索引的指定行

    pandas索引复合索引dataframe数据.索引其中多个水平(level)的多个数据行(index rows from different levels and combine).使用元组tupl ...

  7. pandas索引复合索引dataframe数据、索引其中一个水平(level)的特定数据列(index a column of a level)

    pandas索引复合索引dataframe数据.索引其中一个水平(level)的特定数据列(index a column of a level) 目录

  8. Pandas中xs()函数索引复合索引数据的不同切面数据(索引复合索引中需要的数据):索引列复合索引中的一个切面、索引行复合索引中的一个切面

    Pandas中xs()函数索引复合索引数据的不同切面数据(索引复合索引中需要的数据):索引列复合索引中的一个切面.索引行复合索引中的一个切面 目录

  9. mysql联合索引(复合索引)详解

    这是一篇转自 itlab.idcquan.com的文章,原文地址:http://itlab.idcquan.com/linux/MYSQL/925211.html 联合索引又叫复合索引.对于复合索引: ...

最新文章

  1. AS3 中强制类型转换方法
  2. AD的PCB板设计中PCB板的开槽
  3. 浅谈常见的NoSQL技术方案和选型
  4. 项目5 BBS博客项目
  5. OpenCV-扩充图像边界cv::copyMakeBorder
  6. mysql+修改数据恢复_MySQL 误操作后数据恢复(update,delete忘加where条件)
  7. 医学知识图谱构建关键技术及研究进展
  8. 数字信号处理实验(五)—— 心电信号处理 IIR FIR滤波综合题(上篇)
  9. wma转mp3怎么弄_mp3格式转换器如何把wma转mp3格式(教程)
  10. 华为云发布《云原生2.0架构白皮书》,GaussDB技术再升级
  11. 游戏感:虚拟感觉的游戏设计师指南——第七章 响应的测量方法
  12. Mybatis异常:Invalid bound statement (not found): com.xxx.mapper.xxxMapper.selectByExample
  13. python制作二维码生成器3.0
  14. Prometheus监控告警
  15. 替代A4988的微型打印机驱动TMI8421国产电机驱动芯片
  16. Spring MVC 学习总结(一)——MVC概要与环境配置 转载自【张果】博客
  17. 实例演示Nginx重写(Rewrite)类型last、break、redirect和permanent的区别
  18. ArcGIS二次开发入门(一)
  19. 佛朗斯冲击港交所IPO:叉车租赁的未来是数字化?
  20. ajax参数xhrfields,使用xhrFields可以将进度功能添加到jQuery.ajax()中吗?

热门文章

  1. 如何用Redis实现分布式锁
  2. 【Java基础】数组转字符串
  3. 网页模板克隆扒仿站软件
  4. Python 正则提取
  5. js如何生成唯一标识符UUID
  6. python定时播放音乐程序_python写的定时播放音乐
  7. 具有测绘资质的“八大GPS地图提供商”
  8. 解决升级MIUI 14后不能使用google pay
  9. mysql的datepart函数_MySql 的查询语句中有没有Datepart函数?
  10. LaTex---安装教程(完美版)--Texlive+Ctex+WinEdt+sumatrapdf