- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章MySQL的索引,你真的有好好理解过吗?由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
哈喽大家好!我是小三。今天我们来讲索引.
「索引的概念」:索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里的所有记录的引用指针。通俗来说就是数据库索引就好像是一本书的目录,能够加快数据库的查询速度.
「索引的作用」:索引存在的目的就是在于提高查询效率,使得原始的随机全表扫描变成了快速顺序锁定数据 。
1、普通索引:这是最基本的索引,没有任何的限制 。
2、唯一索引:引列的值必须唯一,但允许有空值(注意和主键不同) 。
3、组合索引:多个数据列组成的索引,遵守了最左匹配原则 。
1、把查询过程中的随机事件变成了顺序事件 。
2、数据保存在磁盘上,而为了提高性能,每次又可以把一部分的数据读入内存来计算,访问磁盘的成本大概是访问内存的十万倍左右.
3、考虑到磁盘IO是非常高昂的操作,计算机操作系统做了一系列的优化,当进行一次IO时,不光把当前磁盘的地址的数据也把相邻的数据也都读取到内存的缓冲区之内。因为局部的预读性原理告诉了我们,当计算机访问一个地址的数据的时候,与它响铃的数据也会很快被访问到。每一次IO读取的数据我们都称之为一页(page)。具体一页会有多大的数据,这跟操作系统有关,一般为4k或者是8k.
我们知道磁盘读取时间=寻道时间+旋转时间+传输时间,当需要从磁盘读取到数据的时候,系统会将数据的逻辑地址传给磁盘,磁盘的控制电路按照寻址逻辑将逻辑地址翻译成了物理地址,就确定了要读的数据 在哪一个磁道,哪个扇区。为了读取扇区的数据,需要将磁头放到扇区的上方,为了实现这一点,磁头需要移动对准相应的磁道,这个过程叫寻道,在这里所耗费的时间叫做寻道时间,然后磁盘旋转目标扇区旋转到磁头下,这个过程耗费的时间叫做旋转时间.
我们使用索引的目的,自然是要提高查询的效率。例如像字典,如果要查询"mysql"这个单词,我们首先肯定是要定位到m字母,然后从下往下找到y字母,以此类推.
查询要求:等值查询,还有范围查询(>、<、between、in)、模糊查询(like)、并集查询(or) 。
数据量:超过一千万数据通过索引查询,查询性能保证 。
顺序检索:最基本的查询算法-复杂度O(n),数据量大的话这个算法的效率是糟糕的 。
二叉树查找:O(log2n),单层节点所能存储数据量较少,需要进行遍历多层才能拿到数据,总结点数k与高度h的关系为k=(2^h)-1 。
hash索引:无法满足范围查找,但是它的等值检索快,hash值==》物理地址x018,范围检索 。
B-Tree:每个节点都是一个二元数组:[key,data],所有的节点都可以存储数据,key为索引key,data为除之外的数据 。
B+Tree数据结构高性能解析 。
B-Tree的缺点:插入删除新的数据记录会破坏掉B-Tree的性质,因此在插入删除时,需要对树进行一个分裂、合并、转移等操作来保持B-Tree的性质。在区间查找时可能需要返回上层节点重新,IO操作繁琐.
B+Tree的改进:非叶子节点不存储data,只存储了索引的key,只有叶子节点才存储data 。
「高性能的保证」:
第1、3层的b+树可以表示上百万的数据,如果上百万的数据查找只需要进行三次IO的话,那么对性能的提高无疑是巨大的,如果没有索引的话,每个数据项都要发生一次IO那么就会有百万次的IO,这显然成本非常非常高.
第2、在B+Tree的每个叶子节点增加一个指向相邻子节点的指针,这样就形成了带有顺序访问指针的B+Tree 。
第3、B+Tree只在叶子节点来存储数据,所有的叶子节点包含一个链指针,其他内存的非叶子节点只存储索引数据。只利用索引快速的定位数据索引范围,先定位索引再通过索引高效的定位数据.
Mysql Server层的优化器负责的是选择索引,而优化器选择索引的目的就是要找到一个最优的执行方案,并且用最小代价来执行语句。在数据库里面,扫描行数是影响执行代价的因素之一。扫描的行数越少,也就意味着访问的磁盘的数据次数就越小,消耗的CPU就越少。扫描行数并不是唯一的判断标准,优化器还会结合了是否使用临时表、是否排序等等因素来综合判断.
Mysql在真正开始执行语句之前,并不可以精确的知道满足该查询条件的记录究竟有多少条,只能根据统计的信息来估算记录数。所以这个统计信息就是索引的“区分度”。显然,一个索引上面的值不同得越多,这个索引的区分度就越好。在一个索引上不同值的个数,称为基数.
那么,mysql是怎么样得到索引基数的?在这里mysql采样统计方法,但是为什么要使用采样统计这种方法呢?原因就是因为如果把整张表取出来然后进行一行行的统计,虽然这样能够得到精确的数据,但是代价也太高了,所以的话只能使用采样统计.
「为什么会出现这种结果呢?」 。
在多个的索引情况下,优化器一般会通过比较了扫描行数、是否需要临时表以及是否需要排序等因素来作为索引的半段依据.
选择了索引b,则就需要在b索引上扫描9W条记录,然后回到主键索引上过滤掉不满足a条件的记录,因为索引有序,所以使用b索引不需要额外排序.
「解决方案」 。
使用force index a让mysql直接选择a索引来处理此处的查询 。
在其他的场景:
数据表有频繁的删除或者是更新操作导致的数据空洞造成的,造成的原因可能是分析器explain的结果预估的rows值跟实际的情况差距比较大,分析器分析扫描行数用的是抽样调查。统计分析不对话可以使用analyze table test命令,用来重新统计索引信息.
「1.查询上的区别」 。
对唯一索引,由于索引定义了唯一性,查到第一个满足条件的记录之后,就会停止检索.
对普通索引,查找到满足条件的第一个记录'ab'后,需要找下个记录,直到碰到第一个不满足k='ab'条件的记录 。
「2.修改上的区别」 。
对于唯一索引,所有更新操作要先判断该操作是否会违反唯一性约束,唯一索引不会用change buff,若所修改的数据在内存当中,找到索引所对应的存储位置、判断到没有冲突,然后再插入值,语句执行结束。若所修改的数据不在内存当中,则需要将数据页也读入内存,判断到没有冲突,再插入值,语句执行结束.
「3.性能上的区别」 。
普通索引查找数据的时候会将符合条件的都给查找出来 。
唯一索引主要是第一条符合条件的就会立即返回,不会在继续查找了,因为唯一的为数已经确保了只有一条符合条件 。
原文链接:https://mp.weixin.qq.com/s/7YeDcMg1Mh_Z4jMrnuNE7A 。
最后此篇关于MySQL的索引,你真的有好好理解过吗?的文章就讲到这里了,如果你想了解更多关于MySQL的索引,你真的有好好理解过吗?的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
这个问题在这里已经有了答案: 关闭 12 年前。 Possible Duplicate: Why can't Python handle true/false values as I expect?
我是不是遗漏了什么或者这是 ruby 中的错误? a = %w(foo bar baz) a.include? "foo" # => true a.size == 3
从 Modelica 文档来看,注释 Evaluate 似乎只对参数有影响: https://build.openmodelica.org/Documentation/ModelicaReferenc
为了避免嵌套的 if 语句并提高可读性,我想创建一个switch(true){ ... } Coldfusion 中的声明。我在 php 中经常使用这个,但是当我在 Coldfusion 中尝试这个时
嗨,我正在尝试处理 ajax json 响应 这是我的代码 success: function (j) { switch(true) { case (j.cho
我之前在我的 TF 代码中使用过这个: count = "${var.whatever == "true" ? 1 : 0}" 这非常适合我想要使用的东西。但是,我正在考虑如何最好地使用类似于说的
我之前在我的 TF 代码中使用过这个: count = "${var.whatever == "true" ? 1 : 0}" 这非常适合我想要使用的东西。但是,我正在考虑如何最好地使用类似于说的
这个问题在这里已经有了答案: How can I return pivot table output in MySQL? (10 个答案) 关闭 5 年前。 我正在尝试构建一个以唯一列值作为列名的表
我制作了一个简单的 JDialog,其中包含一个标签和一个按钮,它基本上相当于信息对话框。所以在对话框中,有一个方法 display() 我在其中调用了 setVisible(true) 五次。 据我
在 bash 4.2.8(1)-release (x86_64-pc-linux-gnu) 在 Ubuntu 11.04 上这个命令 [ $(wc -l /var/www/some.log|cut -
我正在使用 c 语言进行并发处理,我有一个进程池。为此,我让每个 child 都在一个 While (True) 循环中。为了杀死 child ,我正在使用一个全局变量和一个信号处理程序来修改它来打破
我正在尝试选择填写了字段的数据库条目。数据库有两种插入数据的方式,一种输入评论,一种不输入,我希望只选择填写了评论的行。 $requete = "SELECT * FROM daysoff WHER
如何在 JavaMail session 中setDebug(true) 捕获流并在我的日志记录框架中使用它? (缺少下载源代码,更改接受流作为参数的方法,重新编译它,...) 更一般地说,Java
我是 JavaScript 的新手,我刚刚发现了我无法理解的奇怪行为: var magicVar = Math.sin; magicVar == true; // it returns false m
对此感到困惑。 在两台服务器上运行相同版本的 MySQL。 (从完全相同的 rpm 构建)- 沿线的某个地方,一些开发人员改变了一些东西...... 服务器 1: mysql> select ( no
我在查看 OpenSSL 中使用的一些预处理器宏时,从 crypto/stack/safestack.h 中发现了以下内容: #define CHECKED_STACK_OF(type, p) \
所以我遇到了一个问题,我的正则表达式看起来像这样:/true|false/。 当我检查单词 falsee 时,我从这个正则表达式中得到一个 true,有没有办法将它限制为确切的 true 或 fals
我正在对这个恶意 JavaScript 行进行一些试验:var undefined = true; JavaScript 中每个未初始化的变量都有 undefined 的值,这只是一个保存特殊值 'u
我想将 PHP 的微时间存储为我在 MySQL 中的时间戳。 我去过told最好用 DECIMAL 存储它,但我找不到理想的大小。 有谁知道 microtime(true) 返回的最大大小是多少,所以
在 PHP 中,当您在 URL 中包含诸如“var=true”之类的内容时,URL 中的“true”和“false”是否被转换为 boolean 变量,或者它们是否等于文本“true”还是“假”?例如
我是一名优秀的程序员,十分优秀!