索引对查询的速度有着至关重要的影响,理解索引也是进行数据库性能调优的起点。考虑如下情况,假设数据库中一个表有10^6条记录,DBMS的页面大小为4K,并存储100条记录。如果没有索引,查询将对整个表进行扫描,最坏的情况下,如果所有数据页都不在内存,需要读取10^4个页面,如果这10^4个页面在磁盘上随机分布,需要进行10^4次I/O,假设磁盘每次I/O时间为10ms(忽略数据传输时间),则总共需要100s(但实际上要好很多很多)。如果对之建立B-Tree索引,则只需要进行log100(10^6)=3次页面读取,最坏情况下耗时30ms。这就是索引带来的效果,很多时候,当你的应用程序进行SQL查询速度很慢时,应该想想是否可以建索引。

磁盘IO&预读

磁盘读取数据靠的是机械运动,每次读取数据花费的时间可以分为寻道时间、旋转延迟、传输时间三个部分,寻道时间指的是磁臂移动到指定磁道所需要的时间,主流磁盘一般在5ms以下;旋转延迟就是我们经常听说的磁盘转速,比如一个磁盘7200转,表示每分钟能转7200次,也就是说1秒钟能转120次,旋转延迟就是1/120/2 = 4.17ms;传输时间指的是从磁盘读出或将数据写入磁盘的时间,一般在零点几毫秒,相对于前两个时间可以忽略不计。那么访问一次磁盘的时间,即一次磁盘IO的时间约等于5+4.17 = 9ms左右。

考虑到磁盘IO是非常高昂的操作,计算机操作系统做了一些优化,当一次IO时,不光把当前磁盘地址的数据,而是把相邻的数据也都读取到内存缓冲区内,因为局部预读性原理告诉我们,当计算机访问一个地址的数据的时候,与其相邻的数据也会很快被访问到。每一次IO读取的数据我们称之为一页(page)。具体一页有多大数据跟操作系统有关,一般为4k或8k,也就是我们读取一页内的数据时候,实际上才发生了一次IO

B+树

如果要查找数据项29,那么首先会把磁盘块1由磁盘加载到内存,此时发生一次IO,在内存中用二分查找确定29在17和35之间,锁定磁盘块1的P2指针,(内存时间因为非常短),通过磁盘块1的P2指针的磁盘地址把磁盘块3由磁盘加载到内存,发生第二次IO,29在26和30之间,锁定磁盘块3的P2指针,通过指针加载磁盘块8到内存,发生第三次IO,同时内存中做二分查找找到29,结束查询,总计三次IO。真实的情况是,3层的b+树可以表示上百万的数据,如果上百万的数据查找只需要三次IO,性能提高将是巨大的,如果没有索引,每个数据项都要发生一次IO,那么总共需要百万次的IO,显然成本非常非常高。

通过上面的分析我们知道,IO次数取决于树的高度,假设表中的数据为N,每页存储的数据量为m,如果N量一定则m越大数的高度越低IO越少,速度越快,所以我们索引的字段尽量小。

当B+TREE的数据项为符合结构的时候,例(name,age,city)B+TREE是从左往右查找,比如当(张三,20,上海)查找的时候,会先比较name来确定下来的搜索方向,如果name相同在依次比较age和city。
如果是(20,上海)这样子没有name的数据过来,B+树就不知道改查那个节点,因为简历搜索树的时候name是第一个比较因子,所以必须要先根据name来搜索才知道。这个也是最左前缀的逻辑

创建索引的原则

最左前缀原则,非常重要的原则,mysql会一直向右匹配知道遇到(> < between like)就停止,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到。

=和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式,b,d的顺序可以任意调整。

尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0。

尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可,因为创建(a,b)相当于创建了a索引,(a,b)索引

索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’);

补充:

mysql两种类型索引,主键索引也就是聚簇索引,数据记录就存在索引的最底层的叶子节点上,我们的表都会加一个主键。还有一种索引是二级索引或者说是普通索引,这个索引的最底层叶子节点上存的是对应行的主键索引值,所以通过非主键索引找到主键索引值,然后再去主键索引中找数据记录。 对于(A,B,C)组合索引怎么存储这个我不太清楚,对于查询中给出了a,b,c的值如果把a,b,c看成一个整体那么就和单列索引查找b树没有区别,如果只给出了a,应该也可以缩小查找范围不会全表扫描,再给出b再次缩小查找范围。

innodb操作磁盘的单位是否应该是innodb的页面大小,而不是磁盘块大小,也就是说索引数的叶子节点是一个innodb页面,如果要想索引树层次少,应该是要这个innodb的页面大,有些做法改了mysql源码把页面大小增大了,应该就是为了存更多数据同时保持索引数不会太高,提升性能,只是页面碎片变多,磁盘利用率下降。

mysql索引简单分析的更多相关文章

  1. Mysql 索引优化分析

    MySQL索引优化分析 为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学会MySQL性能下降的原因,索引的简介,索引创建的原则,explain命令的使用,以及explain输出字 ...

  2. mySql索引优化分析

    MySQL索引优化分析 为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学会MySQL性能下降的原因,索引的简介,索引创建的原则,explain命令的使用,以及explain输出字 ...

  3. MySQL 索引性能分析概要

    上一篇文章 MySQL 索引设计概要 介绍了影响索引设计的几大因素,包括过滤因子.索引片的宽窄与大小以及匹配列和过滤列.在文章的后半部分介绍了 数据库索引设计与优化 一书中,理想的三星索引的设计流程和 ...

  4. mysql索引利弊分析

    转载自:http://blog.csdn.net/linminqin/article/details/44342205  索引的利弊与如何判定,是否需要索引 相信读者都知道索引能够极大地提高数据检索的 ...

  5. MySQL索引性能分析

    为什么要做性能分析 你有没有这样的情况. 面对一个你没怎么写过的.复杂的业务,你构思了很久,终于开始敲下了第一段代码. 写的过程迷迷糊糊,有的时候还能把自己搞晕了. 但你还是终于把它写完了. 但是点击 ...

  6. Mysql索引类型分析

    一.简介   MySQL目前主要有以下几种索引类型:   1.普通索引   2.唯一索引   3.主键索引   4.组合索引   5.全文索引   二.语句 CREATE TABLE table_na ...

  7. MySql索引原理分析

    面试 问:数据库中最常见的慢查询优化方式是什么? 同学A:加索引. 问:为什么加索引能优化慢查询?同学A:...不知道同学B:因为索引其实就是一种优化查询的数据结构,比如Mysql中的索引是用B+树实 ...

  8. mysql索引简单介绍

    索引从本质上来说也是一种表,这样的表存储被列为索引的列项值和指向真正完整记录的指针.索引对用户透明.仅仅被数据库引擎用来加速检索真实记录.有索引的表.insert和update操作会耗费很多其它时间而 ...

  9. MySQL协议简单分析

     tcpdump -i eth0 -s0  -l -w - port 3306|strings|grep -i -E 'select|update|insert|delete|set' 

随机推荐

  1. django网站地图sitemap

    网站地图是根据网站的结构.框架.内容,生成的导航网页,是一个网站所有链接的容器.很多网站的连接层次比较深,蜘蛛很难抓取到,网站地图可以方便搜索引擎或者网络蜘蛛抓取网站页面,了解网站的架构,为网络蜘蛛指 ...

  2. C#连接数据库open函数失败

    错误信息:在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接. (provider ...

  3. dict使用

    里面的元素是:key: value d = { 'Adam':95, 'Lisa':85, 'Bart':59, 'Paul':75 } 打印:print d['Paul'] 注意:  通过 key ...

  4. springboot之启动方式

    我们在ideal中启动springboot项目时时不需要加载Tomcat容器的,直接在启动类启动就行了,原因是springboot项目中默认包含了内置Tomcat //springboot项目必须引入 ...

  5. Codeforces 1077 F2 - Pictures with Kittens (hard version)

    F2 - Pictures with Kittens (hard version) 思路: 单调队列优化dp 代码: #pragma GCC optimize(2) #pragma GCC optim ...

  6. Codeforces 1053 B - Vasya and Good Sequences

    B - Vasya and Good Sequences 思路: 满足异或值为0的区间,必须满足一下条件: 1.区间中二进制1的个数和为偶数个; 2.区间二进制1的个数最大值的两倍不超过区间和. 如果 ...

  7. Asp.net core 学习笔记 ( ef core )

    更新 : 2018-11-26 这里记入一下关于 foreignKey cascade action 默认情况下如果我们使用 data annotation required + foreginkey ...

  8. 合并k个排序的列表 Merge k Sorted Lists

    2018-11-25 22:58:52 问题描述: 问题求解: 本题可以使用优先队列高效的进行求解,整体的时间复杂度为O(nlogk). public ListNode mergeKLists(Lis ...

  9. Axure 全局变量公式的使用和局部变量

    全局变量和全部变量的公式: 1.全局变量在当前用例所有的动作里面都有,都可以设置 2.全局变量的公式在中括号里面的变量可以运算,但是在中括号外面的变量只是起到连接的作用 局部变量: 局部变量只可以在当 ...

  10. 在python中使用正则表达式(三)

    这里主要说一下贪婪匹配和非贪婪匹配  贪婪匹配:匹配尽可能多的字符:  非贪婪匹配:匹配尽可能少的字符 python的正则匹配默认是贪婪匹配 例子: >>> re.match(r'^ ...