2024年10月mysql索引匹配原则(Mysql建索引的注意事项)

 更新时间:2024-10-12

  ⑴mysql索引匹配原则(Mysql建索引的注意事项

  ⑵Mysql建索引的注意事项

  ⑶最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(》、《、between、like)就停止匹配,比如a=andb=andc》andd=如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。.=和in可以乱序,比如a=andb=andc=建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。.尽量选择区分度高的列作为索引,区分度的公式是count(distinctcol)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是,而一些状态、性别字段可能在大数据面前区分度就是,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要join的字段我们都要求是.以上,即平均条扫描条记录。.索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time)=’--’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time=unix_timestamp(’--’)。.尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。.“一个顶三个“。建了一个(a,b,c)的复合索引,那么实际等于建了(a),(a,b),(a,b,c)三个索引,因为每多一个索引,都会增加写操作的开销和磁盘空间的开销。对于大量数据的表,这可是不小的开销!.覆盖索引。同样的有复合索引(a,b,c,如果有如下的sql:selecta,b,cfromtablewherea=andb=。那么MySQL可以直接通过遍历索引取得数据,而无需回表,这减少了很多的随机io操作。减少io操作,特别的随机io其实是dba主要的优化策略。所以,在真正的实际应用中,覆盖索引是主要的提升性能的优化手段之一.索引列越多,通过索引筛选出的数据越少。有W条数据的表,有如下sql:select*fromtablewherea=andb=andc=,假设假设每个条件可以筛选出%的数据,如果只有单值索引,那么通过该索引能筛选出W*%=w条数据,然后再回表从w条数据中找到符合b=andc=的数据,然后再排序,再分页;如果是复合索引,通过索引筛选出w*%*%*%=w,然后再排序、分页,哪个更高效,一眼便知

  ⑷联合索引最左匹配原则

  ⑸最左匹配原则:最左优先,以最左边的为起点任何连续的索引都能匹配上。同时遇到范围查询(》、《、between、like)就会停止匹配。假如建立联合索引(a,b,cselect*fromtable_namewherea=’’andb=’’andc=’’select*fromtable_namewhereb=’’anda=’’andc=’’select*fromtable_namewherec=’’andb=’’anda=’’......用到了索引where子句几个搜索条件顺序调换不影响查询结果,因为Mysql中有查询优化器,会自动优化查询顺序select*fromtable_namewherea=’’select*fromtable_namewherea=’’andb=’’select*fromtable_namewherea=’’andb=’’andc=’’都从最左边开始连续匹配,用到了索引select*fromtable_namewhereb=’’select*fromtable_namewherec=’’select*fromtable_namewhereb=’’andc=’’这些没有从最左边开始,最后查询没有用到索引,用的是全表扫描select*fromtable_namewherea=’’andc=’’如果不连续时,只用到了a列的索引,b列和c列都没有用到如果列是字符型的话它的比较规则是先比较字符串的第一个字符,第一个字符小的哪个字符串就比较小,如果两个字符串第一个字符相通,那就再比较第二个字符,第二个字符比较小的那个字符串就比较小,依次类推,比较字符串。如果a是字符类型,那么前缀匹配用的是索引,后缀和中缀只能全表扫描了select*fromtable_namewherealike’As%’;//前缀都是排好序的,走索引查询select*fromtable_namewherealike’%As’//全表查询select*fromtable_namewherealike’%As%’//全表查询select*fromtable_namewherea》anda《可以对最左边的列进行范围查询select*fromtable_namewherea》anda《andb》;多个列同时进行范围查找时,只有对索引最左边的那个列进行范围查找才用到B+树索引,也就是只有a用到索引,在《a《的范围内b是无序的,不能用索引,找到《a《的记录后,只能根据条件b》继续逐条过滤如果左边的列是精确查找的,右边的列可以进行范围查找select*fromtable_namewherea=andb》;a=的情况下b是有序的,进行范围查找走的是联合索引一般情况下,我们只能把记录加载到内存中,再用一些排序算法,比如快速排序,归并排序等在内存中对这些记录进行排序,有时候查询的结果集太大不能在内存中进行排序的话,还可能暂时借助磁盘空间存放中间结果,排序操作完成后再把排好序的结果返回客户端。Mysql中把这种再内存中或磁盘上进行排序的方式统称为文件排序。文件排序非常慢,但如果order子句用到了索引列,就有可能省去文件排序的步骤select*fromtable_nameorderbya,b,climit;因为b+树索引本身就是按照上述规则排序的,所以可以直接从索引中提取数据,然后进行回表操作取出该索引中不包含的列就好了orderby的子句后面的顺序也必须按照索引列的顺序给出,比如select*fromtable_nameorderbyb,c,alimit;这种颠倒顺序的没有用到索引select*fromtable_nameorderbyalimit;select*fromtable_nameorderbya,blimit;这种用到部分索引select*fromtable_namewherea=orderbyb,climit;联合索引左边列为常量,后边的列排序可以用到索引CREATETABLEuser_pwd_history(idbigint()NOTNULLAUTO_INCREMENT,user_idbigint()NOTNULL,user_nameVARCHAR()NULLDEFAULT’’,passwordvarchar()NOTNULL,created_attimestampNOTNULLDEFAULTCURRENT_TIMESTAMP,PRIMARYKEY(id),KEYidx_userId_password(user_id,password)USINGBTREE,KEYidx_userName_password(user_nameASC,passwordASC)USINGBTREE)ENGINE=InnoDB;INSERTINTOtest.user_pwd_history(id,user_id,user_name,password,created_at)VALUES(’’,’’,’drc’,’afcdfafceca’,’--::’);INSERTINTOtest.user_pwd_history(id,user_id,user_name,password,created_at)VALUES(’’,’’,’aaa’,’cbda’,’--::’);INSERTINTOtest.user_pwd_history(id,user_id,user_name,password,created_at)VALUES(’’,’’,’ghj’,’cbacbbdb’,’--::’);INSERTINTOtest.user_pwd_history(id,user_id,user_name,password,created_at)VALUES(’’,’’,’ujm’,’fefbefaeabedfee’,’--::’);INSERTINTOtest.user_pwd_history(id,user_id,user_name,password,created_at)VALUES(’’,’’,’ydd’,’acfdbeebdaec’,’--::’);INSERTINTOtest.user_pwd_history(id,user_id,user_name,password,created_at)VALUES(’’,’’,’sss’,’fdffaeeebfa’,’--::’);--走索引,索引覆盖explainselectpasswordfromuser_pwd_historywherepassword=’’;--走索引explainselectcount(*)fromuser_pwd_historywherepassword=’’;--不走索引,最左匹配原则explainselect*fromuser_pwd_historywherepassword=’’;--走索引,最左匹配原则explainselect*fromuser_pwd_historywhereuser_id》;--走索引,只对最左侧user_id范围查询走索引,password不走explainselect*fromuser_pwd_historywhereuser_id》andpassword=’cfbcddaedcbfcaedee’;--全值匹配,走索引explainselect*fromuser_pwd_historywhereuser_id=andpassword=’fefbefaeabedfee’;--模糊查询在后面,前面字符串精确,走索引explainselect*fromuser_pwd_historywhereuser_namelike’As%’;--模糊查询在前面,不走索引,全表扫描explainselect*fromuser_pwd_historywhereuser_namelike’%As’;————————————————原文链接:

  ⑹MySQL索引机制(详细+原理+解析)

  ⑺MySQL前缀索引能有效减小索引文件的大小,提高索引的速度。但是前缀索引也有它的坏处:MySQL不能在ORDERBY或GROUPBY中使用前缀索引,也不能把它们用作覆盖索引(CoveringIndex)。

  ⑻集一个索引包含多个列(最左前缀匹配原则

  ⑼索引列的值必须唯一,但允许有空值

  ⑽全文索引为FUllText,在定义索引的列上支持值的全文查找,允许在这些索引列中插入重复值和空值,全文索引可以在CHAR,VARCHAR,TEXT类型列上创建

  ⑾设定主键后数据会自动建立索引,InnoDB为聚簇索引

  ⑿即一个索引只包含单个列,一个表可以有多个单列索引

  ⒀覆盖索引是指一个查询语句的执行只用从所有就能够得到,不必从数据表中读取,覆盖索引不是索引树,是一个结果,当一条查询语句符合覆盖索引条件时候,MySQL只需要通过索引就可以返回查询所需要的数据,这样避免了查到索引后的回表操作,减少了I/O效率

  ⒁普通的索引,没有什么介绍

  ⒂查看:(注意和前缀索引Sub_part的区别

  ⒃当索引的列是unique的时候,会生成唯一索引,唯一索引关于null有下列两种情况

  ⒄SQLSERVER下的唯一索引的列,允许null值,但最多允许有一个空值

  ⒅MYSQL下的唯一索引的列,允许null值,并且允许多个空值

  ⒆会建立两个索引,一个非聚簇索引,一个是唯一索引

  ⒇可以插入两个空值(明人不说暗话,我喜欢MySQL

  ⒈一方面,它不会索引所有字段所有字符,会减小索引树的大小.

  ⒉另外一方面,索引只是为了区别出值,对于某些列,可能前几位区别很大,我们就可以使用前缀索引。

  ⒊一般情况下某个前缀的选择性也是足够高的,足以满足查询性能。对于BLOB,TEXT,或者很长的VARCHAR类型的列,必须使用前缀索引,因为MySQL不允许索引这些列的完整长度。

  ⒋复合索引的最左前缀匹配原则:

  ⒌对于复合索引,查询在一定条件才会使用该索引

  ⒍减少开销。建一个联合索引(col,col,col),实际相当于建了(col),(col,col),(col,col,col)三个索引。每多一个索引,都会增加写操作的开销和磁盘空间的开销。对于大量数据的表,使用联合索引会大大的减少开销!

  ⒎覆盖索引。对联合索引(col,col,col),如果有如下的sql:selectcol,col,colfromtestwherecol=andcol=。那么MySQL可以直接通过遍历索引取得数据,而无需回表,这减少了很多的随机io操作。减少io操作,特别的随机io其实是dba主要的优化策略。所以,在真正的实际应用中,覆盖索引是主要的提升性能的优化手段之一。

  ⒏效率高。索引列越多,通过索引筛选出的数据越少。有W条数据的表,有如下sql:selectfromtablewherecol=andcol=andcol=,假设假设每个条件可以筛选出%的数据,如果只有单值索引,那么通过该索引能筛选出W%=w条数据,然后再回表从w条数据中找到符合col=a如果“%”不是在第一位,索引就会使用

  ⒐多列索引是在表的多个字段上创建的索引,满足最左前缀匹配原则,索引才会被使用

  ⒑查询语句只有Or关键字时候,如果OR前后的两个条件都是索引,这这次查询将会使用索引,否则Or前后有一个条件的列不是索引,那么查询中将不使用索引

  ⒒mysql建索引的几大原则

  ⒓.选择唯一性索引唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。例如,学生表中学号是具有唯一性的字段。为该字段建立唯一性索引可以很快的确定某个学生的信息。如果使用姓名的话,可能存在同名现象,从而降低查询速度。.为经常需要排序、分组和联合操作的字段建立索引经常需要ORDERBY、GROUPBY、DISTINCT和UNION等操作的字段,排序操作会浪费很多时间。如果为其建立索引,可以有效地避免排序操作。.为常作为查询条件的字段建立索引如果某个字段经常用来做查询条件,那么该字段的查询速度会影响整个表的查询速度。因此,为这样的字段建立索引,可以提高整个表的查询速度。.限制索引的数目索引的数目不是越多越好。每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间就越大。修改表时,对索引的重构和更新很麻烦。越多的索引,会使更新表变得很浪费时间。.尽量使用数据量少的索引如果索引的值很长,那么查询的速度会受到影响。例如,对一个CHAR()类型的字段进行全文检索需要的时间肯定要比对CHAR()类型的字段需要的时间要多。.尽量使用前缀来索引如果索引字段的值很长,最好使用值的前缀来索引。例如,TEXT和BLOG类型的字段,进行全文检索会很浪费时间。如果只检索字段的前面的若干个字符,这样可以提高检索速度。.删除不再使用或者很少使用的索引表中的数据被大量更新,或者数据的使用方式被改变后,原有的一些索引可能不再需要。数据库管理员应当定期找出这些索引,将它们删除,从而减少索引对更新操作的影响。.最左前缀匹配原则,非常重要的原则。mysql会一直向右匹配直到遇到范围查询(》、《、between、like)就停止匹配,比如a=””and=””b=””c=”“》andd=如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。.=和in可以乱序。比如a=andb=andc=建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。.尽量选择区分度高的列作为索引。区分度的公式是count(distinctcol)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是,而一些状态、性别字段可能在大数据面前区分度就是,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要join的字段我们都要求是.以上,即平均条扫描条记录.索引列不能参与计算,保持列“干净”。比如from_unixtime(create_time)=’--’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time=unix_timestamp(’--’);.尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可注意:选择索引的最终目的是为了使查询的速度变快。上面给出的原则是最基本的准则,但不能拘泥于上面的准则。读者要在以后的学习和工作中进行不断的实践。根据应用的实际情况进行分析和判断,选择最合适的索引方式。

  ⒔Mysql索引最左匹配原则

  ⒕他是按照索引的字段,第一个字段排序,相等的话,则看第二个字段比较大小。所以如果查询条件跳过第一个字段,直接查询第二、第三,或者是第三字段的话,那么这个是无序的,自然用不了索引。

  ⒖则explain后的执行情况是:

  ⒗mysql的索引最左原则就很清晰了。索引多个字段,会按照字段顺序依次比较大小建立索引,如果跳过这个顺序的话,则索引失效。前提是没有其他索引进行影响

  ⒘二叉搜索树、N叉树页分裂:B+树的插入可能会引起数据页的分裂,删除可能会引起数据页的合并,二者都是比较重的IO消耗,所以比较好的方式是顺序插入数据,这也是我们一般使用自增主键的原因之一。页分裂逆过程:页合并,当删除数据后,相邻的两个数据页利用率很低的时候会做数据页合并主键索引:key:主键,value:数据页,存储每行数据非主键索引:key:非主键索引,value:主键key,导致回表最左匹配:优先将区分度高的列放到前面,这样可以高效索引,最左匹配原则遇到范围查询就停止匹配,范围查询(》、《、between、like)为什么?因为出现范围匹配后,后面的索引字段无法保证有序,局部有序失去,顺序失去则无法提高查询效率SELECT*FROMtableWHEREaIN(,,)andb》;如何建立索引?还是对(a,b)建立索引,因为IN在这里可以视为等值引用,不会中止索引匹配,所以还是(a,b)!索引组织表索引用页存储:key【】-point【】,通过调整key大小,当页大小固定的情况下,通过调整key大小,使得N叉树变化;如key,point则单个索引字节,页大小为k,则页面总共可以存储个索引,即N大小覆盖索引:二级索引的信息已经存在想要的列,例如主键如果现在有一个高频请求,要根据市民的身份证号查询他的姓名,这个联合索引就有意义了。它可以在这个高频请求上用到覆盖索引,不再需要回表查整行记录,减少语句的执行时间。索引下推优化:可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。整理索引碎片,重建表:altertableTengine=InnoDB??首先是看key的大小,另外是数据页的大小,如果需要改变N,则需要从这两个方面做改动;一个innoDB引擎的表,数据量非常大,根据二级索引搜索会比主键搜索快,文章阐述的原因是主键索引和数据行在一起,非常大搜索慢,我的疑惑是:通过普通索引找到主键ID后,同样要跑一边主键索引,对于使用覆盖索引的情况下,使用覆盖索引可以直接解决问题

  ⒙mysql---索引优化

  ⒚索引就是为特定的mysql字段进行一些特定的算法排序,比如二叉树的算法和哈希算法,哈希算法是通过建立特征值,然后根据特征值来快速查找。.普通索引:(index)最基本的索引,没有任何限制?目的:加快数据的查询速度.唯一索引:(unique)?与“普通索引“类似,不同的就是:索引列的值必须唯一,但允许有空值。.主键索引(primarykey)它是一种特殊的唯一索引,不允许有空值。.复合索引:index(a,b,c)?为了更多的提高mysql效率可建立组合索引,遵循”最左前缀“原则。.全文索引:fulltext?仅可用于MyISAM表,针对较大的数据,生成全文索引很耗时耗空间。第一类是myisam存储引擎使用的叫做b-tree结构,第二类是innodb存储引擎使用的叫做聚簇结构(也是一种b-tree。如下图:注意:.myisam不需要回行处理?.innodb不需要回行处理,直接可以获取数据,因为innodb的储存引擎是包含了数据和索引文件的,其主键索引包含了数据,(唯一索引及普通索是没有直接包含数据的)、索引列不能参与计算?有索引列参与计算的查询条件对索引不友好(甚至无法使用索引,如from_unixtime(create_time)=’--’。?原因很简单,如何在节点中查找到对应key?如果线性扫描,则每次都需要重新计算,成本太高;如果二分查找,则需要针对from_unixtime方法确定大小关系。因此,索引列不能参与计算。上述from_unixtime(create_time)=’--’语句应该写成create_time=unix_timestamp(’--’)。、最左前缀匹配?如有索引(a,b,c,d),查询条件a=andb=andc》andd=,则会在每个节点依次命中a、b、c,无法命中d。也就是最左前缀匹配原则。、冗余和重复索引??冗余索引是指在相同的列上按照相同的顺序创建的相同类型的索引,应当尽量避免这种索引,发现后立即删除。比如有一个索引(A,B),再创建索引(A)就是冗余索引。冗余索引经常发生在为表添加新索引时,比如有人新建了索引(A,B),但这个索引不是扩展已有的索引(A)、避免多个范围条件????selectuser.*fromuserwherelogin_time》’--’andagebetweenand;?比如想查询某个时间段内登录过的用户:它有两个范围条件,login_time列和age列,MySQL可以使用login_time列的索引或者age列的索引,但无法同时使用它们.、覆盖索引(能扩展就不新建)?如果一个索引包含或者说覆盖所有需要查询的字段的值,那么就没有必要再回表查询,这就称为覆盖索引。覆盖索引是非常有用的工具,可以极大的提高性能,因为查询只需要扫描索引会带来许多好处:.索引条目远小于数据行大小,如果只读取索引,极大减少数据访问量.索引是有按照列值顺序存储的,对于I/O密集型的范围查询要比随机从磁盘读取每一行数据的IO要少的多、选择区分度高的列作索引如,用性别作索引,那么索引仅能将w行数据划分为两部分(如w男,w女,索引几乎无效。区分度的公式是count(distinct)/count(*),表示字段不重复的比例,比例越大区分度越好。唯一键的区分度是,而一些状态、性别字段可能在大数据面前的区分度趋近于。、删除长期未使用的索引场景一(覆盖索引)索引应该建在选择性高的字段上(键值唯一的记录数/总记录条数,选择性越高索引的效果越好、价值越大,唯一索引的选择性最高;组合索引中字段的顺序,选择性越高的字段排在最前面;where条件中包含两个选择性高的字段时,可以考虑分别创建索引,引擎会同时使用两个索引(在OR条件下,应该说必须分开建索引;不要重复创建彼此有包含关系的索引,如index(a,b,c)、index(a,b)、index(a);组合索引的字段不要过多,如果超过个字段,一般需要考虑拆分成多个单列索引或更为简单的组合索引;不要滥用索引。因为过多的索引不仅仅会增加物理存储的开销,对于插入、删除、更新操作也会增加处理上的开销,而且会增加优化器在选择索引时的计算代价。因此太多的索引与不充分、不正确的索引对性能都是毫无益处的。一言以蔽之,索引的建立必须慎重,对每个索引的必要性都应该经过仔细分析,要有建立的依据。

  ⒛mysql有几种索引类型使用索引时都有那些地方要注意sql优化原则是什么

  mysql的索引类型及使用索引时的注意事项有:

  普通索引。这是最基本的索引,它没有任何限制。它有以下几种创建方式:

  CREATEINDEXindexNameONmytable(username(length));

  如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定length,下同。

  ALTERmytableADDINDEXON(username(length))--创建表的时候直接指定

  CREATETABLEmytable(??IDINTNOTNULL,???usernameVARCHAR()NOTNULL,??INDEX(username(length))??);

  --删除索引的语法:

  DROPINDEXONmytable;

  唯一索引。它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:

  CREATEUNIQUEINDEXindexNameONmytable(username(length))--修改表结构ALTERmytableADDUNIQUEON(username(length))--创建表的时候直接指定CREATETABLEmytable(??IDINTNOTNULL,???usernameVARCHAR()NOTNULL,??UNIQUE(username(length))??);

  主键索引。它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引:

  CREATETABLEmytable(??IDINTNOTNULL,???usernameVARCHAR()NOTNULL,??PRIMARYKEY(ID)??);

  当然也可以用ALTER命令。记住:一个表只能有一个主键。

  组合索引。为了形象地对比单列索引和组合索引,为表添加多个字段:

  CREATETABLEmytable(??IDINTNOTNULL,???usernameVARCHAR()NOTNULL,??cityVARCHAR()NOTNULL,??ageINTNOTNULL?);

  为了进一步榨取MySQL的效率,就要考虑建立组合索引。就是将name,city,age建到一个索引里:

  ALTERTABLEmytableADDINDEXname_city_age(name(),city,age);建表时,usernname长度为,这里用。这是因为一般情况下名字的长度不会超过,这样会加速索引查询速度,还会减少索引文件的大小,提高INSERT的更新速度。

  如果分别在usernname,city,age上建立单列索引,让该表有个单列索引,查询时和上述的组合索引效率也会大不一样,远远低于我们的组合索引。虽然此时有了三个索引,但MySQL只能用到其中的那个它认为似乎是最有效率的单列索引。

  建立这样的组合索引,其实是相当于分别建立了下面三组组合索引:usernname,city,age??usernname,city??usernname?为什么没有city,age这样的组合索引呢?这是因为MySQL组合索引“最左前缀”的结果。简单的理解就是只从最左面的开始组合。并不是只要包含这三列的查询都会用到该组合索引,下面的几个SQL就会用到这个组合索引:

  SELECT*FROMmytableWHREEusername=“admin“ANDcity=“郑州“?SELECT*FROMmytableWHREEusername=“admin“

  简述mysql最左原则

  最左原则顾名思义就是从最左边开始匹配的原则,mysql会一直向右匹配直到遇到范围查询(》、《、between、like)就停止匹配,索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式,其针对的是组合索引(又名联合索引。假设我们现在对A、B、C三个字段建立组合索引,来剖析什么时候会用到索引。A=nickName,B=groupId,C=sign。首先来看下我的表结构和索引如图-,在这里就不作过多赘述。我先来介绍下图中sql在expalin执行计划后得一些参数。id:为选择标识符。select_type:表示查询的类型,SIMPLE表示简单的select,没有union和子查询。table:输出结果集的表。partitions:匹配的分区。type:表示表的连接类型,range是指给定范围内的检索,比如?in(xx,xx)或者?between。该类最好的时候是const(即表示为通过索引一次就找到了,最差的时候是all(需要遍历全表。possible_keys:表示查询时,可能使用的索引。(显示可能应用在这张表中的索引,不一定能应用到。key:表示实际使用的索引。key_len:索引字段的长度。ref:列与索引的比较。rows:找到所需的记录所需要读取的行数。filtered:按表条件过滤的行百分比。Extra:执行情况的描述和说明。由图的key字段看出A、B、C下,我们使用上了nickName_id_sign联合索引,rows字段看出,读取了行。那我们来看看B、C、A与C、B、A呢?图-看出B、C、A与C、B、A也用到了索引,为什么呢?这是因为当客户端把SQL语句传送到服务器后,服务器进程会对该语句进行解析。这个解析的工作是在服务器端所进行的,解析动作又可分为很多小动作。其中最重要的一步就是确定最佳执行计划。服务器进程会根据一定的规则,对这条语句进行优化。(在执行计划开始之前会有一步查询转换,如:视图合并、子查询解嵌套、谓语前推及物化视图重写查询等。【此处不理解可以忽略,大概可以理解为优化器寻找最低成本的执行计划】。最终确定可能的最低成本的执行计划。当服务器进程的优化器确定这条查询语句的最佳执行计划后,就会将这条SQL语句与执行计划保存到数据高速缓存,提高SQL语句处理效率。在mysql中会使用IndexMergeintersectionalgorithm算法来调整条件子句顺序(可以理解为上面所表述的寻找最低成本的执行计划),详情请看官方文档。由图可以看出A、B组合也使用到了索引,看到type值为ref(非唯一性索引扫描,返回匹配某个单独值的所有行,本质上也是一种索引访问,它返回所有匹配某个单独值的行,它可能会找到多个符合条件的行,所以他应该属于查找和扫描的混合体。,再看rows,为条,比A、B、C下略多,但还好,可以接受。由图可以看出A、C组合也使用到了索引,可以看到key_len索引中使用的字节数比A、B、C与A、B下小得多,再看rows,为七万多条,filtered的过滤条件仅为百分之十,这是因为A、B、C组合索引覆盖了(A、(A,B、(A,B,C三个索引点击查看官方文档,而A、C组合用到了A索引,我们来看图只有A条件nickName下与图的rows参数都一致。filtered参数不一致是因为where的后置条件决定其过滤比例的。图可看出B、C组合下没有用到索引,type类型为ALL遍历整表去寻找记录,possible_keys与key都为空,rows几乎为全表记录。这是因为组合索引的最左匹配原则,mysql会根据A来确定下一步的搜索方向,当没有A时,就只能去全记录去寻找。有什么问题请留言,大家一起探讨学习???。

  在mysql中,索引是一种特殊的数据库结构,由数据表中的一列或多列组合而成,可以用来快速查询数据表中有某一特定值的记录。

  通过索引,查询数据时不用读完记录的所有信息,而只是查询索引列即可。

  通过索引,查询数据时不用读完记录的所有信息,而只是查询索引列。否则,数据库系统将读取每条记录的所有信息进行匹配。

  可以把索引比作新华字典的音序表。例如,要查“库”字,如果不使用音序,就需要从字典的页中逐页来找。但是,如果提取拼音出来,构成音序表,就只需要从多页的音序表中直接查找。这样就可以大大节省时间。

  因此,使用索引可以很大程度上提高数据库的查询速度,还有效的提高了数据库系统的性能。

  索引有其明显的优势,也有其不可避免的缺点。

  通过创建唯一索引可以保证数据库表中每一行数据的唯一性。

  可以给所有的MySQL列类型设置索引。

  可以大大加快数据的查询速度,这是使用索引最主要的原因。

  在实现数据的参考完整性方面可以加速表与表之间的连接。

  在使用分组和排序子句进行数据查询时也可以显著减少查询中分组和排序的时间

  增加索引也有许多不利的方面,主要如下:

  创建和维护索引组要耗费时间,并且随着数据量的增加所耗费的时间也会增加。

  索引需要占磁盘空间,除了数据表占数据空间以外,每一个索引还要占一定的物理空间。如果有大量的索引,索引文件可能比数据文件更快达到最大文件尺寸。

  当对表中的数据进行增加、删除和修改的时候,索引也要动态维护,这样就降低了数据的维护速度。

  使用索引时,需要综合考虑索引的优点和缺点。

您可能感兴趣的文章:

相关文章