Mysql优化-索引

 

 

1. 索引的本质

  MySQL官方对索引的定义为:索引是帮助MySQL高效获取数据的数据结构。

  数据库查询是数据库的最主要功能之一。我们都希望查询数据的速度尽可能的快,因此

数据库系统的设计者会从查询算法的角度进行优化。最基本的查询算法是顺序查找(liner search),这种复杂度为o(n)的算法在数据量大时,速度很慢。但是我们有更优秀的查找算法,例如二分查找(binary search)、二叉树查找(binary tree search)等。如果稍微分析一下会发现,每种查找算法都只能用于特定的数据结构之上,例如二分查找要求被检索数据有序,而二叉查找只能应用于二叉查找树上,但是数据本身的组织结构不可能满足各种数据结构(例如,一般不可能同时将两列都按顺序进行组织),所以在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实训高级查找算法。这种数据结构,就是索引。

  为了加快查询速度,可以维护一个二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录物理地址的指针,这样就可以运用二叉查找在o(logN)的复杂度内获取到相应数据。

  虽然这是一个货真价实的索引,但是实际的数据库系统几乎没有使用二叉查找树实现的。。。

 

二叉排序树

  二叉排序树的排序规则如下:

  1)若左子树不空,则左子树上所有节点的值均小于它的根节点的值

  2)若右子树不空,则右子树上所有节点的值均大于它的根节点的值

  3)它的左右子树也分别是二叉排序树(递归定义)

 

  二叉排序树组织数据时,用于查找是比较方便的,因为每次经过一次节点时,最多可以减少一半的可能,不过极端情况的出现所有节点都位于同一侧,直观上看就是一条直线,那么这种查询的效率就比较低了,因此需要对二叉树左右子树的高度进行平衡化处理,于是就有了平衡二叉树(Balanced Binary Tree)。

  所谓的“平衡”,说的是这棵树的各分支的高度是均匀的,它的左右子树高度差的绝对值小于等于1,这样就不会出现一条支路特别长的情况。于是,在这样的平衡树种进行查找是,总共比较节点的次数不超过数的高度,这就确保了查询的效率(时间复杂度为o(logN))

 

B树

  B树实际上是一种平衡的多叉查找树,也就是说最多可以开 m 个叉(m >= 2),我们称之为 m 阶B树。

  B树的查询过程和二叉排序树比较类似,从根节点依次比较每个节点,因为每个节点中的关键字和左右子树都是有序的,所以只要比较节点中的关键字,或者沿着指针就能很快的找到指定的关键字,如果查找失败,则会返回叶子节点,即空指针。

  B树的特点可以总结如下:

  1)关键字集合分布在整棵树中;

  2)任何一个关键字出现且只出现在一个节点中。

  3)搜索有可能在非叶子节点结束

  4)其搜索性能等价于在关键字集合内做二分查找

  5)B树在插入删除新的数据记录会破坏B-Tree的性质,因为在插入删除时,需要对树进行一个分裂、合并、转义等操作,以保持B-Tree的性质。

 

 B+ 树

  作为B树的加强版,B+树与B树的差异在于

  1)有 n 棵子树的节点含有 n 个关键字(n-1个关键字)

  2)所有的关键字全部存储在叶子节点上,且叶子节点本身根据关键字自小而大顺序连接

   3)非叶子节点可以看成索引部分,节点中仅含有其子树(根节点)中的最大(或最小)关键字。

 

  B+ 树的查找过程,与B树类似,只不过查找时,如果在非叶子节点上的关键字等于给定值,并不终止,而是继续沿着指针直到叶子节点位置。因此在B+树,不管查找是否成功,每次查找都是走了一条从根到叶子节点的路径。

 

 B+ 树的特性如下:

  1)所有关键字都存储在叶子节点上,且链表中的关键字恰好是有序的。

  2)不可能非叶子节点命中返回。

  3)非叶子节点相当于叶子节点的索引,叶子节点相当于是存储(关键字)数据的数据层。

  4)更适合文建索引系统。

 

带有顺序访问指针的B+Tree

  一般在数据库系统或文件系统中使用的 B+Tree 结构都在经典 B+Tree 的基础上进行了优化,增加了顺序访问指针。

  

 

  在 B+Tree 的每个叶子节点增加一个指向相邻叶子节点的指针,就形成了带有顺序访问指针的 B+Tree。做这个优化的目的是为了提高区间访问的性能。如上图,要查询key从18到49的所有数据记录,当找到18后,只需顺着节点和指针顺序遍历就可以一次性访问到所有数据节点,极大提高了区间查询效率。

 

MySQL为什么使用B树(B+树)

  一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上。这样的话,索引查找过程中就要产生磁盘 I/O 消耗,相对于内存存取,I/O存取的消耗要高几个数量级,所以评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘 I/O 的操作次数的渐进复杂度。换句话说,索引的结构组织要尽量减少查找过程中磁盘 I/O 的存取次数。

  由于存储介质的特性,磁盘本身存取就比主存慢很多,再加上机械运动耗费,磁盘的存取速度往往是主存的几百分之一,因此为了提高效率,要尽量减少磁盘 I/O 。为了达到这个目的,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序往后读取一定长度的数据放入内存。这样做的理论依据是计算机科学中注明的局部性原理:

  当一个数据被用到时,其附近的数据也通常会马上被使用。

  所以,程序运行期间所需要的数据通常应当比较集中。

  由于磁盘顺序读取的效率很高(不需要寻道,只需要很少的旋转时间),因此对于具有局部性的程序来说,预读可以提高 I/O 效率。预读的长度一般为页的整数倍。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割成连续的大小相等的块,每个存储块称为一页(大小通常为4K),主存和磁盘以页为单位交换数据。当程序要读取的数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,磁盘会找到数据的起始位置并向后连续读取一页或几页载入内存中,然后异常返回,程序继续运行。

 

B-/+Tree 索引的性能分析

  上文说一般使用磁盘 I/O 次数评价索引结构的优劣。

  B-Tree 检索一次最多需要访问 h 个节点。数据库系统的设计者巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次 I/O 就可以完全载入。为了达到这个目的,在实际实现 B-Tree 还需要使用如下技巧:

  每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐的,就实现一个 node 只需一次 I/O 。

  B-Tree 中一次检索最多需要 h-1 次 I/O (根节点常驻内存),渐进复杂度为 o(h)=o(logN) d 为底。实际,出度 d 是非常大的数字,通常超过100,因此 h 非常小(通常不超过3)。(h 表示树的高度 & 出度 d 表示的是树的度,即树中各节点度的最大值)

   综上,用 B-Tree 作为索引结构效率是非常高的。

  而红黑树(二叉平衡查找树),h 明显深得多。由于逻辑上很近的节点(父子)物理上可能很远,无法利用局部性,所以,红黑树的 I/O 渐进复杂度也为 o(h),效率明显比 B-Tree 差很多。

   

  上文还说,B+Tree 更适合外存索引,原因和内节点出度 d 有关。从上面分析可知,d 越大索引性能越好,而出度的上限取决于节点内 key 和 data 的大小:

  dmax = floor(pagesize / (keysize + datasize + pointsize))

  由于 B+Tree 内节点去掉了data 域,因此可以拥有更大的出度,有更好的性能。

 

MySQL索引实现

  在MySQL中,索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的,本文主要讨论MyIsam 和 InnoDB 两个存储引擎实现方式。

  MyIsam 引擎使用 B+Tree 作为索引结构,叶节点的 data 域存放的是数据记录的地址。下图是 MyIsam 索引的原理图:

 

  这里设表一共有三列,假设我们以 col1 为主键,则上图是一个 MyIsam表的主索引(Primary key)示意。可以看出 MyIsam 的索引文件仅仅保存数据记录的地址。在 MyIsam 中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的 key 可以重复。如果我们在 col2 上建立一个辅助索引,则次索引的结构如下图所示:

    

 

   同样也是一棵 B+Tree data域保存数据记录的地址。因此,MyIsam中索引检索的算法为首先按照 B+Tree 搜索算法搜索索引,如果指定的key存在,则取出其 data 域的值,然后以 data 域的值为地址,读取相应数据记录。

  MyIsam 的索引方式也叫做“非聚集”的,之所以这么称呼是为了与 InnoDB 的聚集索引区分。

 

InnoDB 索引实现

  虽然 InnoDB 也使用 B+Tree 作为索引结构,但具体实现方式却与 MyIsam 截然不同。

  第一个重大区别是 InnoDB 的数据文件本身就是索引文件。从上文知,MyIsam 索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。而在 InnoDB 中,表数据文件本身就是按 B+Tree 组织的一个索引结构,这棵树的叶节点 data 域保存了完整的数据记录。这个索引的 key 是数据表的主键,因此 InnoDB 表数据文件本身就是主索引。

   

  InnoDB主索引(同时也是数据文件),其叶子节点包含了完整的数据记录。这种索引叫做聚集索引。因为InnoDB 的数据文件本身要按主键聚集,所以 InnoDB要求表必须有主键(MyIsam可以没有),如果没有显式指定,则MySQL会自动选择一个可以唯一标识数据记录的列为主键,如果不存在这样的列,则MySQL自动为 InnoDB 表生成一个隐含字段为主键,这个字段长度6字节,类型是长整型。

   第二个与MyIsam不同的是InnoDB的辅助索引data域存储相应记录主键的值,而不是地址。换句话说,InnoDB的所有辅助索引都引用主键作为data域。例如,下图的辅助索引:

   

  聚集索引这种实现方式使得按主键搜索十分高效,但是辅助索引需要检索两遍索引:先检查辅助索引获得主键,然后用主键到住索引中检索获得记录。

  了解不同的存储引擎实现方式对于正确使用和优化索引都有帮助,例如知道了 InnoDB 的索引实现后,就容易明白为什么不建议使用过长的字段作为主键,因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大。再例如,用非单调的字段作为主键在 InnoDB 中不太好, 因为 InnoDB 数据文件本身是一棵 B+Tree,非单调的主键会造成在插入新记录时数据文件为了维护 B+Tree 的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择。

 

 

2. 索引的类型

   mysql索引有四种类型:主键索引、唯一索引、普通索引和全文索引。通过给字段添加索引,可以提高数据的读取速度,提高项目的并发能力和抗压能力。索引优化是 mysql 的一种优化方式。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。

 

  主键索引:主键是一种唯一性索引,但它必须指定为 PRIMARY KEY,每个表只能有一个主键。

  alter table tabname add primary key('字段名');

 

  唯一索引:索引列的所有值都只能出现一次,即必须唯一,值可以为 空

  alter table tabname add unique index('字段名');

  

  普通索引:基本的索引类型,值可以为空,没有唯一性的限制

  alter table tabname add index('字段名');

 

  全文索引:全文索引的索引类型为 FULLTEXT。全文索引可以在 varchar、char、text 类型的列上创建。可以通过 ALTER TABLE 或者 CREATE INDEX 命令创建。对于大规模的数据集,通过 ALTER TABLE(或者CREATE INDEX)命令创建全文索引要比把记录插入带有全文索引的空表更快。MyIsam 支持全文索引,InnoDB 在mysql5.6  后支持了全文索引。

  全文索引不支持中文,需要借 sphinx(coreseek)或讯搜<、code>技术处理中文。

  alter table tabname add fulltext('字段名');

 

 

  查看表的所有索引和删除

  show indexes from 表名;

  show keys from 表名;

  alter table 表名 drop index 索引名;

 

 

 

3. 执行计划explain

  explain 显示了 MySQL 如何使用索引来处理 select 语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句,简单说,他的作用就是分析查询性能。
  mysql查看是否使用索引,简单的看 type 类型就可以。如果他是 all,那么说明这条查询语句遍历了所有行,并没有使用索引。
 

  1)id

  执行编号,标识 select 所属的行。如果语句中没有子查询或关联查询,只有唯一的 select ,每行都将显示1.否则,内层的 select 语句一般会顺序编号,对应于其在原始语句中的位置。

  列数字越大越先执行,如果数字一样大,那么就从上到下执行,id列为 null 的就表示这是一个结果集,不需要使用它来进行查询。

 
   2)select_type
  显示本行是简单或复杂 select。如果查询有任何复杂的子查询,则最外层标记为 PRIMARY。
 
  simple:简单子查询,不包含子查询和 union
  primary:包含 union 或者子查询,最外层的部分标记为 primary
  subquery:一般子查询中的子查询被标记为 subquery ,也就是位于 select 列表中的查询
  derived:派生表——该临时表是从子查询派生出来的,位于 from 中的子查询
  union:位于 union 中第二个及其以后的子查询被标记为 union,第一个就被标记为 primary, 如果是 union 位于 from 中则标记为 derived
  union result:用来从匿名临时表里检索结果的 select 被标记为 union result
  dependent union:首先需要满足 union 的条件,及 union 中第二个及后面的 select 语句,同时该语句依赖外部的查询 
  subquery:子查询中第一个select语句
  dependent subquery:和dependent union 相对 union一样
 
 
  3)table
  访问引用哪个表的表名
  • 关联优化器会为查询选择关联顺序,左侧深度优先
  • 当 from 中有子查询的时候,表名是 derivedN 的形式,N指向子查询,也就是 explain 结果中的下一列
  • 当有 union result 的时候,表名是 union 1,2 等的形式,1,2 表示参与 union 的query id
  注意,MySQL 对待这些表和普通表一样,但是这些“临时表”是没有任何索引的。
 
 
  4)type
  数据访问/读取操作类型(ALL、index、range、ref、eq_ref、const/system、NULL)
  type 显示的是访问类型,是较为重要的一个指标,结果从好到坏依次是:
  system > const > eq_ref > ref > fuultext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL,一般来说,得保证查询至少达到 range 级别,最好能达到 ref
  ALL:最坏的情况,全表扫描
  index:和全表扫描一样。只是扫描表的时候按照索引次序进行而不是行。主要优点就是避免了排序,但是开销仍然非常大。如在 Extra 列看到 Using index,说明正在使用覆盖索引(select 的数据只用从索引中就能取得,不用从数据表中取),只扫描索引的数据,它比按索引次序全表扫描的开销要小很多
  range:范围扫描,一个有限制的索引扫描。key 列显示使用哪个索引。当使用 =、<>、>、>=、<、<=、>、>=、IS NULL、<=>、BETWEEN 或者 IN 操作符,用常量比较关键字列时,可以使用 range
  ref:一种索引访问,它返回所有匹配某个单个值的行。此类索引访问只有当使用非唯一索引或唯一索引非唯一性前缀时才会发生。这个类型跟 eq_ref 不同的是,它用在关联操作只使用了索引的最左前缀,或者索引不是 unique 和 primary key。ref 可以用于使用 = 或 <=> 操作符的带索引的列
  eq_ref:最多只返回一条符合条件的记录。使用唯一性索引或主键查找时会发生(高效)
  const:当确定最多只有一行匹配时,MySQL 优化器会在查询前读取它而且只读取一次,因此非常快。当主键放入 where 子句时,mysql 把这个查询转为一个常量(高效)
  system:这是 const 连接类型的一种特例,表仅有一行满足条件
  NULL:意味着 mysql 能在优化阶段分解查询语句,在执行阶段甚至用不到访问表或者索引(高效)
 
 
 
  5)possible_keys
  显示查询使用了哪些索引,表示该索引可以进行高效地查找,但是列出来的索引对于后续优化过程可能是没有用的
 
 
 
  6)key
  显示 mysql 决定采用哪个索引来优化查询。如果没有选择索引,键是 NULL。要想强制 MySQL 使用或忽视 possible_keys 列中的索引,在查询中使用 force index、use index 或者 ignore index。
 
 
 
  7)key_len
  显示 mysql 在索引里使用的键长度。如果键是 NULL,则长度是 NULL。使用的索引的长度,在不损失精确性的情况下,长度越短越好。
 
 
 
  8)ref
  显示使用哪个列或常数与 key 一起从表中选择行
 
 
 
  9)rows
  为了找到所需的行而需要读取的行数,估算值,不精确。通过把所有 rows 列值相乘,可粗略估算整个查询会检查的行数
 
 
 
  10)Extra
  额外信息,如 using index、filesort 等。该列显示 MySQL 在查询过程中的一些详细信息,MySQL查询优化器执行查询过程中对查询计划的重要补充信息。
 
  using filesort:MySQL 有两种方式可以生成有序的结果,通过排序操作或者使用索引,当 Extra 中出现了 using filesort 说明 MySQL 使用了前者,但注意虽然叫 filesort 但并不是说明就是用了文件来进行排序,只要可能排序都是在内存里完成的。大部分情况下利用索引排序更快,所以一般这时也要考虑优化查询了。使用文件完成排序操作,这里可能是 order by,group by 语句的结果,这可能是一个CPU密集型的过程,可以通过选择合适的索引来改进性能,用索引来为查询结果排序。
  
   using temporary:用临时表保存中间结果,常用于 group by 和 order by 操作中,一般看到他说明查询需要优化了,就算避免不了临时表的使用也要尽量避免硬盘临时表的使用。
 
  not exists:mysql 优化了 left join,一旦他找到了匹配 left join 标准的行,就不再搜索了。
  
  using index:说明查询是覆盖了索引的,不需要读取数据文件,从索引树(索引文件)中即可获得信息。如果同时出现 using where,表明索引用来读取数据而非执行查找动作。这是mysql 服务层完成的,但不需再回表查询记录。
 
  using index condition:这是 mysql5.6 出来的新特性,叫做“索引条件推送”。简单说就是 mysql 原来在索引上是不能执行如 like 这样的操作的,但是现在可以了,,这样减少了不必要的 IO 操作,但是只能用在二级索引上。
 
  using where:使用了 where 从句来限制哪些行将与下一张表匹配或者是返回给用户。注意, Extra 列出现 using where 表示 mysql 服务器将存储引擎返回服务层以后再应用 where 条件过滤。
 
  using join buffer:使用了连接缓存:Block Nested Loop,连接算法是块嵌套循环连接;Batched Key Access,连接算法是批量索引连接
 
  impossible where:where子句的值总是 false,不能用来获取任何元组。
 
  select tables optimized away:在没有 group by 子句的情况下,基于索引优化 MIN/MAX 操作,或者对于 MyIsam 存储引擎优化 count(*) 操作,不必等到执行阶段再进行计算,查询执行计划生成的阶段即完成优化。
 
  distinct:优化 distinct 操作,在找到第一匹配的元组后即停止找同样值的动作。
 

 

4. 索引的使用场景

   1)MySQL目前支持前导列

  mysql 只支持最左前缀原则进行筛选

  创建复合索引

 

  2)索引列上的范围查找

  对于某个条件进行范围查找时,如果这个列上有索引,且使用 where ... between and ... >,< 等范围操作,那么可能用到索引范围查找,如果索引范围查找的成本太高,数据库可能会选择全表扫描。

  IN 也是范围查找的范畴,但是带操作函数的 IN 不属于查找的范畴

 

  3)join 列

  在联合查询两个表时,比如查询语句为 select a.col1, b.col2 from a join b on a.id = b.id,其中id 为两个表的主键,如果 a 是小表,那么 a 就被视为驱动表,那么数据库可能全表扫描 a 表,并用 a 表的每一个 id 去探测 b 表的索引查询匹配的记录。

 

  4)where 子句

  形如:

  where a = ? and b = ? and c > 1000

  where a = ? and b = ? and c = ? and d > 1000

  where 子句的条件列是复合索引前面的索引列 + 另一个列的范围查找

 

  create index   idx_a_b_c_d on tb1(a, b, c, d); 

  上面才会用到这个索引。

  下面的两个查询:

  where a=? and b=? and c>1000 and d<10000  这个例子中 d < 10000 这个操作并不会走索引

  where a>? and b=? and c>1000 and d<10000   这个例子 a 上有范围查找,那么 b、c、d 列上的索引信息都不能被利用

  注,创建索引,考虑把复合索引的范围查找放到最后。

 

  5)mysql 优化器

  mysql 优化器会做一些特殊优化,比如对于索引查找 max(索引列)可以直接进行定位。遇到 max, min 是可以在列上做索引。

 

 

 

 

5、索引失效

 https://www.jianshu.com/p/aedf4c0972e8

 https://www.jianshu.com/p/3ccca0444432

   1)where 条件中的索引列不能是表达式的一部分,mysql 不支持函数索引,即对查询的列上有运算或者函数

 

  2)InnoDB 二级索引底层叶子节点存储的是索引+主键值

  InnoDB的非主键索引存储的不是实际的记录的指针,而是主键的值,所以主键最好是整数型,如自增ID,基于主键存取数据是最高效的,使用二级索引存取数据则需要进行二次索引查找。

 

  3)索引尽量是高选择性的,如性别,男女两种情况不宜使用索引,基本会全表扫描

 

 

  4)查询条件中有 or , 仍是全表扫描

 

  5)like 查询是以 ‘%’ 开头

 

  6)如果列类型是字符串,那一定要在条件中将数据使用引号引起来,否则不使用索引。

 explain select name, age, address from user where name=10 ---- 这样的不使用索引,走全表扫描。这里的原因和上面第一条是一样的,首先 mysql 有个类型转换规则就是将字符串转成数字  explain select name, age, address from user where cast(name as signed)=10。很明显,name上有函数,所以不会走索引。

 

  7)左连接查询或者右连接查询关联的字段编码格式不一样

  explain select a.name, b.job from user a left join job b on a.name=b.name

  如果 user 表的 name 字段编码是 utf8mb4, 而 job 表的 name 字段编码是 gbk。执行左外连接查询 b 表仍然走的是全表扫描。

  

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

   数据量很少的情况。

 

   9)连接查询中,按照优化器顺序的第一张表不会走索引

  条件:a 表 name 有索引, b 表name 没有索引

  结果: explain a.name, a.age, b.name, b.job from user a left join job —— a表 b表都是全表扫描

  explain select a.name, a.age, b.name, b.job from user a right join job b on a.name=b.name——a表使用上了索引

  explain select a.name, a.age, b.name, b.job from user a inner join job b on a.name = b.name——a表使用到了索引

   从上面3个连接查询来看只有左外连接a 表没有用到索引的,这就是因为由于是左外连接,所以优化器的执行顺序是 a 表、 b 表,也就是说首先全表扫描 a 表,再根据 a 表的 name 查询 b 表的值,所以 a 表无法用到索引。所以,一般这种连接查询,A表关联B表,要在将优化器顺序的第二张表上关联的字段加索引,而第一张不用加,无用的索引也会影响性能。而第三个例子中的内连接就不一样了,如果是内连接优化器本身就会根据索引情况,连接表的大小去选择执行顺序,所以上例中的内连接执行顺序是 b, a,这样仍然可以用到 a 的索引。

 

  10)如果查询中没有用到联合索引的第一个字段,则不会走索引。

 

 注意:

  索引尽量是高选择性的

  使用更短的索引:可以考虑前缀索引,但应确保选择的前缀的长度可以保证大部分值是唯一的。衡量不同前缀索引唯一值比例,select count(distinct left(col_name, 5))/count(*)) as sele5;  select count(distinct left(col_name, 6))/count(*)) as sele6;  select count(distinct left(col_name, 7))/count(*)) as sele7; 

   避免创建过多的索引:索引过多可能会浪费大量空间,尤其本身字段量较大的字符串,索引过多可能会浪费空间,且降低修改数据的速度,所以不要创建过多的索引,也不要创建重复的索引。

   如果是唯一值的列,创建唯一索引会更佳,也可以确保不会出现重复数据

  使用覆盖索引能大大提高性能:所有数据都可以从索引中得到,而不需要去读物理记录。

  利用索引排序:mysql 有两种方法可以产生有序结果,一种是使用文件排序,另一种是扫描有序的索引,我们尽量使用索引来排序:1)尽量保证索引列和 order by 的列相同,且各列按照相同的顺序排序,2)如果连接多张表,那么 order by 引用的列需要在表连接顺序的首张表内

  添加冗余索引要权衡:如果一个索引 column A ,那么新的索引(columnA, columnB)就是冗余索引。一般情况下不论是新增冗余索引,还是扩展原索引为冗余索引,都会导致索引文件的增大,并且增加了维护索引的开销。比如更改了列值也要对此列所以在索引进行重新排序。

 

 

 

posted @ 2019-08-29 09:50  停不下的时光  阅读(1902)  评论(0编辑  收藏  举报