MySQL使用单列索引和多列索引

标签: mysql 索引 多列 | 发表时间:2014-11-16 00:28 | 作者:jxlanxin
出处:http://www.iteye.com

摘自: http://greatwqs.iteye.com/blog/1897118

 

讨论MySQL选择索引时单列单列索引和多列索引使用,以及多列索引的最左前缀原则。

1. 单列索引

    在性能优化过程中,选择在哪些列上创建索引是最重要的步骤之一。可以考虑使用索引的主要有两种类型的列:在Where子句中出现的列,在join子句中出现的列。请看下面这个查询: 

Sql代码    收藏代码
  1. Select age ## 不使用索引   
  2. FROM people Where firstname='Mike' ## 考虑使用索引   
  3. AND lastname='Sullivan' ## 考虑使用索引  

    这个查询与前面的查询略有不同,但仍属于简单查询。由于age是在Select部分被引用,MySQL不会用它来限制列选择操作。因此,对于这个查询来说,创建age列的索引没有什么必要。

下面是一个更复杂的例子: 

Sql代码    收藏代码
  1. Select people.age, ##不使用索引   
  2. town.name ##不使用索引   
  3. FROM people LEFT JOIN town ON people.townid=town.townid ##考虑使用索引   
  4. Where firstname='Mike' ##考虑使用索引   
  5. AND lastname='Sullivan' ##考虑使用索引  

    与前面的例子一样,由于firstname和lastname出现在Where子句中,因此这两个列仍旧有创建索引的必要。除此之外,由于town表的townid列出现在join子句中,因此我们需要考虑创建该列的索引。 

    那么,我们是否可以简单地认为应该索引Where子句和join子句中出现的每一个列呢?差不多如此,但并不完全。我们还必须考虑到对列进行比较的操作符类型。MySQL只有对以下操作符才使用索引:<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE。

可以在LIKE操作中使用索引的情形是指另一个操作数不是以通配符(%或者_)开头的情形。

例如:

Sql代码    收藏代码
  1. Select peopleid FROM people Where firstname LIKE 'Mich%'  

这个查询将使用索引;但下面这个查询不会使用索引。 

Sql代码    收藏代码
  1. Select peopleid FROM people Where firstname LIKE '%ike';  

2. 多列索引

    索引可以是单列索引,也可以是多列索引。下面我们通过具体的例子来说明这两种索引的区别。假设有这样一个people表: 

 

Sql代码    收藏代码
  1. Create TABLE people (   
  2. peopleid SMALLINT NOT NULL AUTO_INCREMENT,   
  3. firstname CHAR(50) NOT NULL,   
  4. lastname CHAR(50) NOT NULL,   
  5. age SMALLINT NOT NULL,   
  6. townid SMALLINT NOT NULL,   
  7. PRIMARY KEY (peopleid) );  

    下面是我们插入到这个people表的数据:  

    这个数据片段中有四个名字为“Mikes”的人(其中两个姓Sullivans,两个姓McConnells),有两个年龄为17岁的人,还有一个名字与众不同的Joe Smith。 

    这个表的主要用途是根据指定的用户姓、名以及年龄返回相应的peopleid。例如,我们可能需要查找姓名为Mike Sullivan、年龄17岁用户的peopleid: 

Sql代码    收藏代码
  1. Select peopleid  
  2. FROM people   
  3. Where firstname='Mike'   
  4.       AND lastname='Sullivan' AND age=17;  

    由于我们不想让MySQL每次执行查询就去扫描整个表,这里需要考虑运用索引。  

    首先,我们可以考虑在单个列上创建索引,比如firstname、lastname或者age列。如果我们创建firstname列的索引(Alter TABLE people ADD INDEX firstname (firstname);),MySQL将通过这个索引迅速把搜索范围限制到那些firstname='Mike'的记录,然后再在这个“中间结果集”上进行其他条件的搜索:它首先排除那些lastname不等于“Sullivan”的记录,然后排除那些age不等于17的记录。当记录满足所有搜索条件之后,MySQL就返回最终的搜索结果。 

    由于建立了firstname列的索引,与执行表的完全扫描相比,MySQL的效率提高了很多,但我们要求MySQL扫描的记录数量仍旧远远超过了实际所需要的。虽然我们可以删除firstname列上的索引,再创建lastname或者age列的索引,但总地看来,不论在哪个列上创建索引搜索效率仍旧相似。 

    为了提高搜索效率,我们需要考虑运用 多列索引。如果为firstname、lastname和age这三个列创建一个多列索引,MySQL只需一次检索就能够找出正确的结果!下面是创建这个多列索引的SQL命令:  

Sql代码    收藏代码
  1. Alter TABLE people   
  2. ADD INDEX fname_lname_age (firstname,lastname,age);  

    由于索引文件以B-树格式保存,MySQL能够立即转到合适的firstname,然后再转到合适的lastname,最后转到合适的age。在没有扫描数据文件任何一个记录的情况下,MySQL就正确地找出了搜索的目标记录!  

    那么,如果在firstname、lastname、age这三个列上分别创建单列索引,效果是否和创建一个firstname、lastname、age的多列索引一样呢?

    答案是否定的,两者完全不同。当我们执行查询的时候,MySQL只能使用一个索引。如果你有三个单列的索引,MySQL会试图选择一个限制最严格的索引。但是,即使是限制最严格的单列索引,它的限制能力也肯定远远低于firstname、lastname、age这三个列上的多列索引。  

3. 多列索引中最左前缀(Leftmost Prefixing) 

    多列索引还有另外一个优点,它通过称为最左前缀(Leftmost Prefixing)的概念体现出来。继续考虑前面的例子,现在我们有一个firstname、lastname、age列上的多列索引,我们称这个索引为fname_lname_age。当搜索条件是以下各种列的组合时,MySQL将使用fname_lname_age索引: 

firstname,lastname,age

firstname,lastname

firstname

    从另一方面理解,它相当于我们创建了(firstname,lastname,age)、(firstname,lastname)以及(firstname)这些列组合上的索引。下面这些查询都能够使用这个fname_lname_age索引:  

Sql代码    收藏代码
  1. Select peopleid FROM people   
  2. Where firstname='Mike' AND lastname='Sullivan' AND age='17';   
Sql代码    收藏代码
  1. Select peopleid FROM people   
  2. Where firstname='Mike' AND lastname='Sullivan';   
Sql代码    收藏代码
  1. Select peopleid FROM people   
  2. Where firstname='Mike';   

下面这些查询不能够使用这个fname_lname_age索引: 

Sql代码    收藏代码
  1. Select peopleid FROM people   
  2. Where lastname='Sullivan';   

 

Sql代码    收藏代码
  1. Select peopleid FROM people   
  2. Where age='17';   

 

Sql代码    收藏代码
  1. Select peopleid FROM people   
  2. Where lastname='Sullivan' AND age='17';   


已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [mysql 索引 多列] 推荐:

mysql多列索引使用注意

- - C1G军火库
MySQL可以为多个列创建索引. 用于排序的column的排序顺序必须一致. mysql5.1.26rc升级至Percona mysql5.5.17 ( 2011-12-16). mysql InnoDB 版本一览 ( 2011-12-09). (小技巧)用EXCEL的CONCATENATE合并列整理数据 ( 2011-10-11).

MySQL使用单列索引和多列索引

- - 数据库 - ITeye博客
摘自: http://greatwqs.iteye.com/blog/1897118. 讨论MySQL选择索引时单列单列索引和多列索引使用,以及多列索引的最左前缀原则.     在性能优化过程中,选择在哪些列上创建索引是最重要的步骤之一. 可以考虑使用索引的主要有两种类型的列:在Where子句中出现的列,在join子句中出现的列.

mysql处理存在则更新,不存在则插入(多列唯一索引)

- - CSDN博客数据库推荐文章
mysql处理某个唯一索引时存在则更新,不存在则插入的情况应该是很常见的,网上也有很多类似的文章,我今天就讲讲当这个唯一的索引是多列唯一索引时可能会遇到的问题和方法. 使用 INSERT INTO ON. 其中该表中var1、var2和var3完全相同的记录只能有一条,所以建了一个多列唯一索引index_var,这样一来我们就可以使用  INSERT INTO ON.

ElasticSearch 索引 VS MySQL 索引

- - crossoverJie's Blog
这段时间在维护产品的搜索功能,每次在管理台看到 elasticsearch 这么高效的查询效率我都很好奇他是如何做到的. 这甚至比在我本地使用 MySQL 通过主键的查询速度还快. 这类问题网上很多答案,大概意思呢如下:. Lucene 的全文检索引擎,它会对数据进行分词后保存索引,擅长管理大量的索引数据,相对于.

[MySQL] B+树索引

- - CSDN博客推荐文章
B+树是一种经典的数据结构,由平衡树和二叉查找树结合产生,它是为磁盘或其它直接存取辅助设备而设计的一种平衡查找树,在B+树中,所有的记录节点都是按键值大小顺序存放在同一层的叶节点中,叶节点间用指针相连,构成双向循环链表,非叶节点(根节点、枝节点)只存放键值,不存放实际数据. 保持树平衡主要是为了提高查询性能,但为了维护树的平衡,成本也是巨大的,当有数据插入或删除时,需采用拆分节点、左旋、右旋等方法.

mysql 索引技巧

- - 小彰
MySQL索引的建立对于MySQL的高效运行是很重要的. 下面介绍几种常见的MySQL索引类型. 在数据库表中,对字段建立索引可以大大提高查询速度. 假如我们创建了一个 mytable表:. CREATE TABLE mytable(   ID INT NOT NULL,    username VARCHAR(16) NOT NULL  );   我们随机向里面插入了10000条记录,其中有一条:5555, admin.

mysql选择索引

- - CSDN博客数据库推荐文章
1、尽量为用来搜索、分类或分组的数据列编制索引,不要为作为输出显示的数据列编制索引. 最适合有索引的数据列是那些在where子句中数据列,在联结子句中出现的数据列,或者是在Group by 、Order by子句中出现的数据列. select 后的数据列最好不要用索引. 2、综合考虑各数据列的维度.

mysql 索引详解

- - 行业应用 - ITeye博客
本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题. 特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等. 为了避免混乱,本文将只关注于BTree索引,因为这是平常使用MySQL时主要打交道的索引,至于哈希索引和全文索引本文暂不讨论.

mysql索引认识

- - 数据库 - ITeye博客
数据在磁盘中是以 “块”的形式存储的,所以一张表涉及的数据可能会存在多个块中,而在磁盘中查询数据则会根据字段是否为有序与无序来区分,. 无序情况:1.数值具有唯一性则需要查找 总块数/2.                   2.无序+无唯一性则需要查找  总块数. 有序情况:1.数值唯一性:log2(总块数/2)   (log2是二分查找算法).

MySQL 索引方式

- - zzm
本文配图来自《高性能MySQL(第二版)》. 在数据库中,对性能影响最大的几个策略包括数据库的锁策略、缓存策略、索引策略、存储策略、执行计划优化策略. 索引策略决定数据库快速定位数据的效率,存储策略决定数据持久化的效率. MySQL中两大主要存储引擎MyISAM和InnoDB采用了不同的索引和存储策略,本文将分析它们的异同和性能.