8.3优化与索引

在测试中发现,对select 语句提升性能的最好方式是在其查询条件的一列或多列上增加索引。索引的行为如同指针一样,能够快速决定哪些数据行符合查询条件,并且所有的数据类型都可以增加索引。
虽然为每个查询条件中的列都增加索引很有诱惑力,但是不必要的索引会浪费空间和时间(MYSQL需要确定用哪个索引),索引还会增加增、删、改的成本,因为每个索引都需要更新,所以我们必须建立最优的索引。

8.3.1 怎么使用MYSQL索引
索引通常被用于可以快速查询到数据的列值上。如果没有索引MYSQL必须从第一行开始,查询整个表数据,才可以找到目标数据,很明显,表数据越大这个成本越高。所以如果有索引,MYSQL就可以快速定位到目标数据而不需要通过查找所有数据的方式,这注定是更快速的。
大部分MYSQL索引(PRIMARY KEY, UNIQUE, INDEX, and FULLTEXT)是以B-trees存储的。例外的情况有:特殊数据类型(geometry)是用R-trees存储;  MEMORY表也支持hash indexes;InnoDB引擎使用倒排序列表的方式支撑FULLTEXT索引。

一般来说,索引用于以下场景。hash indexes细节在8.3.9章节会介绍
下面的操作MYSQL会使用索引:

  • 利用where从句快速查找目标数据行
  • 为了剔除数据,MYSQL通常会从多个索引中选择查询出数据集合最少的执行(区分度最大的索引)
  • 如果表里存在复合索引,优化器可以正常使用任何左前缀方式的索引。比如有一个包含三列的复合索引(col1,col2,col3),那就具有根据(col1)、(col1、col2)、(col1、col2、col3)利用索引查询的能力。更多信息可以查看 8.3.6:复合索引
  • 对于联合(join)表操作,把索引字段定义为同样的类型和大小会更有效率。在这方面VARCHAR 和CHAR被认为同样的类型,但是请注意字段大小,VARCHAR(10)和CHAR(15)是不一样的。

           对于非二进制的string型列,两列应该用相同的字符集。例如:utf8属性的列和latin1属性的列是无法利用索引的;
           不同类型的列进行比较(比如string类型和时间或数字类型)在不能直接转化的情况下,可能无法使用索引的,比如数字类型的1和任何字符类型的1('1', ' 1', '00001', or '01.e1')相关联,但是它将无法使用索引

  • 为了在某些特定的索引列上找到最大MAX()和MIN()最小值,// todo
  • 在order和group 一个表的操作中,如果存在最左索引(比如说 ORDER BY key_part1, key_part2),如果所有的KEY是降序(DESC),则以倒序读取数据(如果索引是倒序索引则可以以正序的方式读取数据),详情请见 Section 8.2.1.16, “ORDER BY Optimization”, Section 8.2.1.17, “GROUP BY Optimization”, 、 Section 8.3.13, “Descending Indexes”.

在某些情况下,查询语句可以不用查询具体的数据行,因为索引中已经包含了必要的结果字段(如果一个索引能提供查询结果,则这个索引叫做覆盖索引),这样查询速度会更快 

          比如下面:
                 SELECT key_part3 FROM tbl_name
                  WHERE key_part1=1


  索引不适用下面场景
   数据量比较小的表、或者数据量比较大的表,但是要查询大部分甚至所有数据的情况,这种情况下顺序读取比通过索引读取往往更快。顺序读取磁盘会最小次数进行查找,即使不是所有的数据行都需要,详情请见Section 8.2.1.23, “Avoiding Full Table Scans”

上一篇:python boxplot的使用方法


下一篇:MySQL 视图(合并多表数据)引发的严重性能问题