索引的三星原则

1.索引将相关的记录放到一起,则获得一星

2.如果索引中的数据顺序和查找中的排列顺序一致则获得二星

3.如果索引中的列包含了查询中的需要的全部列则获得三星

多列索引

1.1、多个单列索引

  很多人对多列索引的理解都不够。一个常见的错误就是,为每个列建立独立的索引,或者按照错误的顺序创建多列索引。

  我们会在稍后的章节中单独讨论索引列的顺序问题。先来看第一个问题,为每个列创建独立的索引,从SHOW CREATE TABLE 中很容易看到这种情况:

CREATE TABLE t(
 c1 INT,c2 INT , c3 INT ,KEY(c1),KEY(c2),KEY(c3)
);

  这种索引策略,一般是由于人们听到一些专家诸如“把WHERE 条件里面的列都建上索引”这样模糊的建议导致的。实际上这个建议是非常错误的。这样一来最好的情况也只能是“一星”索引,其性能比起真正最有效的索引可能差几个数量级。有时如果无法设计出一个“三星”索引,那么不如忽略掉WHERE 子句,集中精力优化索引列的顺序,或者创建一个全覆盖索引。

索引合并

  在多个列上建立独立的单列索引大部分情况下不能提高MySQL的查询性能。MySQL5.0和更高的版本医用了一种叫“索引合并”策略,一定程度上可以使用表上的多个单列索引来定位指定的行。更早版本的MySQL只能使用其中某一个单列索引,然而这种情况下没有哪一个独立索引是非常有效的。例如在film_actor在字段film_id和actor_id上各有一个单列索引。但是对于这个查询WHERE 条件,这两个单列索引都不是好的选择:

SELECT film_id ,actor_id FROM film_actor WHERE actor_id=1 or film_id =1;

  在老的MySQL版本中,MySQL对于这个查询是会使用全表扫描的,除非改写成如下的两个查询UNION的方式:

SELECT film_id ,actor_id FROM film_actor WHERE actor_id=1
  UNION ALL
  SELECT film_id ,actor_id FROM film_actor WHERE film_id=1;

但是在MySQL5.0 和更高的版本中,查询能够同时使用者两个单列索引进行扫扫描,并将结果进行合并。这种算法有三个变种:OR条件的联合(union),AND条件的相交(intersection),组合前面两种情况的联合及相交。下面的查询就是使用了两个索引扫描的联合,通过EXPLAIN中的Extra列可以看出这点:

EXPLAIN SELECT film_id,actor_id FROM film_actor WHERE actor_id=1 or film_id = 1 \G

 

MySQL会使用这类技术优化负责的查询,所以在某些语句的EXTRA列中还可以看到嵌套操作。

  索引合并策略有时候是一种优化的结构,但实际上更多的时候说明了表上的索引建的很糟糕

  当出现服务器对多个索引做相交操作(通常有多个AND条件),通常意味着需要一个包含所有相关列的多个索引,而不是独立的单列索引。

  当服务器需要对多个索引做联合操作(通常有多个OR条件),通常需要耗费大量的cpu和内存资源在算法的缓冲,排序和合并的操作上。特别是当其中有些索引的选择性不高。需要合并扫描返回大量数据的时候。

  更重要的是,优化器不会吧这些成本算到“查询成本”中,游虎丘只关心随机页面读取。这会使得查询成本被低估,导致该执行计划还不如直接走全表扫描。这样做不但会消耗更多的cup和内存资源,还可能影响查询的并发性,但如果是单独鱼腥这样的查询则往往会忽略对并发现的影响。通常来说,还不弱在MySQL4.1或更早的时代一样,将查询改写成UNION的方式往往会更好。

如果在Explain语句中看到索引合并,应该好好检查一下查询和表的结构。也可以通过参数optimizer_switch来关闭索引合并功能。也可以使用IGNORE_INDEX提示让优化器忽略掉某些索引。

==========================================================================================

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

ALTER TABLE people ADD INDEX fname_lname_age (firstname,lastname,age); 

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

那么,如果在firstname、lastname、age这三个列上分别创建单列索引,效果是否和创建一个firstname、lastname、age的多列MySQL数据库索引一样呢?答案是否定的,两者完全不同。当我们执行查询的时候,MySQL只能使用一个索引。如果你有三个单列的MySQL数据库索引,MySQL会试图选择一个限制最严格的索引。

但是,即使是限制最严格的单列索引,它的限制能力也肯定远远低于firstname、lastname、age这三个列上的多列索引。

索引是快速搜索的关键。MySQL索引的建立对于MySQL的高效运行是很重要的。

1.2、复合索引

联合索引又叫复合索引。对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。例如索引是key index (a,b,c)。 可以支持a | a,b| a,b,c 3种组合进行查找,但不支持 b,c进行查找 .当最左侧字段是常量引用时,索引就十分有效。两个或更多个列上的索引被称作复合索引。

见《mysql索引之四:复合索引之最左前缀原理,索引选择性,索引优化策略之前缀索引

 

mysql索引之五:多列索引的更多相关文章

  1. 正确理解Mysql的列索引和多列索引

    MySQL数据库提供两种类型的索引,如果没正确设置,索引的利用效率会大打折扣却完全不知问题出在这. CREATE TABLE test ( id         INT NOT NULL, last_ ...

  2. mysql索引之一:索引基础(B-Tree索引、哈希索引、聚簇索引、全文(Full-text)索引区别)(唯一索引、最左前缀索引、前缀索引、多列索引)

    没有索引时mysql是如何查询到数据的 索引对查询的速度有着至关重要的影响,理解索引也是进行数据库性能调优的起点.考虑如下情况,假设数据库中一个表有10^6条记录,DBMS的页面大小为4K,并存储10 ...

  3. 认识SQLServer索引以及单列索引和多列索引的不同

     一.索引的概念 索引的用途:我们对数据查询及处理速度已成为衡量应用系统成败的标准,而采用索引来加快数据处理速度通常是最普遍采用的优化方法. 索引是什么:数据库中的索引类似于一本书的目录,在一本书中使 ...

  4. Atitit.  单列索引与多列索引 多个条件的查询原理与设计实现

    Atitit.  单列索引与多列索引 多个条件的查询原理与设计实现 1. MySQL只能使用一个索引1 1.1. 最左前缀1 1.2. 从另一方面理解,它相当于我们创建了(firstname,last ...

  5. Mysql的列索引和多列索引(联合索引)

    转自:http://blog.chinaunix.net/uid-29305839-id-4257512.html 创建一个多列索引:CREATE TABLE test (      id       ...

  6. MySQL Index--关联条件列索引缺失导致执行计划性能不佳

    某系统反馈慢SQL影响生产,查看SLOW LOG发现下面慢SQL: SELECT COUNT(DISTINCT m.batch_no) FROM ob_relation r INNER JOIN ob ...

  7. MySQL 最左前缀(Leftmost Prefix) & 组合索引(复合索引,多列索引)

    资料来源于网络,仅供参考学习. CREATE TABLE test(a INT,b INT,c INT,KEY idx(a,b,c)); 优: SELECT * FROM test WHERE a=1 ...

  8. mysql多列索引和最左前缀

    数据库的索引可以加快查询速度,原因是索引使用特定的数据结构(B-Tree)对特定的列额外组织存放,加快存储引擎(索引是存储引擎实现)查找记录的速度.索引优化是数据库优化的最重要手段. 如果查询语句使用 ...

  9. mysql索引之四(索引使用注意规则:索引失效--存在索引但不使用索引)

    但是如果是同样的sql如果在之前能够使用到索引,那么现在使用不到索引,以下几种主要情况: 1. 随着表的增长,where条件出来的数据太多,大于15%,使得索引失效(会导致CBO计算走索引花费大于走全 ...

  10. mysql索引之三:索引使用注意规则(索引失效--存在索引但不使用索引)*

    使用索引时,有以下一些技巧和注意事项: (1)越小的数据类型通常更好:越小的数据类型通常在磁盘.内存和CPU缓存中都需要更少的空间,处理起来更快.(2)简单的数据类型更好:整型数据比起字符,处理开销更 ...

随机推荐

  1. SQL语句中各个部分的执行顺序(转)

    原文链接:http://www.tuicool.com/articles/fERNv2 写在前面的话:有时不理解SQL语句各个部分执行顺序,导致理解上出现偏差,或者是书写SQL语句时随心所欲,所以有必 ...

  2. cursor游标(mysql)

    /* 游标 cursor 什么是游标?为什么需要游标 使用存储过程对sql进行编程的时候,我们查询的语句可能是数据是多个,它总是一口气全部执行,我们无法针对每一条进行判断.也就是说,我们无法控制程序的 ...

  3. Data truncated for column

    数据类型不合法造成的.检查插入的数据.

  4. 继承users表,添加新字段成一个新表

    1. Tools > Run manage.py Task 创建app,users startapp users 2.修改users中的models from django.db import ...

  5. Vue学习笔记 ——computed VS methods

    对于最终的结果,两种方式确实是相同的.然而,不同的是计算属性是基于它们的依赖进行缓存的.计算属性只有在它的相关依赖发生改变时才会重新求值.这就意味着只要 message 还没有发生改变,多次访问 re ...

  6. vue 之 vue-router

    官方文档 // 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter) // 1. 定义(路由)组件. // 可以从其他文件 import 进来 c ...

  7. 使用django搭建博客并部署

    2017/8/31 18:27:59 为了以后参考的方便,在这里总结一下django搭建博客网站的主要步骤.以下大部分的内容,参考自Django中文文档 - 看云. 需要强调的是,这里使用的djang ...

  8. Jmeter简单的接口测试

    1.新建线程组 2.编辑线程组信息 3.在线程组中添加HTTP信息头管理器 4.配置HTTP信息头管理器 参数格式配置 5.在线程组中添加HTTP请求 6.编辑HTTP请求信息 7.添加响应断言 8. ...

  9. 如何向整个 Git 仓库补提交一个文件

    微软在 Reference Source 里开放了 .Net Framework 多个版本的源码.为了更方便地阅读这些源码,我们把每一个版本都下载下来后按顺序提交到 git 仓库中. 但是!!!居然忘 ...

  10. Thinkphp 下 MySQL group by 接count 获得条数方法

    比如 下面的语句 , 用于分组统计 select count(*) from es_diabetes where uid=43658 GROUP BY uniques 结果明显不是我们想要得,为什么呢 ...