当前位置: 首页 > news >正文

中国建设银行积分商城网站专业网站开发

中国建设银行积分商城网站,专业网站开发,温州设计集团,哈尔滨工程招标信息网知识点#xff1a;Mysql 索引原理完全手册(1) 知识点#xff1a;Mysql 索引原理完全手册(2) 知识点#xff1a;Mysql 索引优化实战(3) 知识点#xff1a;Mysql 数据库索引优化实战(4) Mysql-索引原理完全手册 一、 介绍二、 索引的原理三、 索引的数据结构四、 聚集索引与辅…   知识点Mysql 索引原理完全手册(1) 知识点Mysql 索引原理完全手册(2) 知识点Mysql 索引优化实战(3) 知识点Mysql 数据库索引优化实战(4) Mysql-索引原理完全手册 一、 介绍二、 索引的原理三、 索引的数据结构四、 聚集索引与辅助索引五、 MySQL索引管理六、 测试索引七、 正确使用索引八、 联合索引与覆盖索引九、 查询优化神器-explain十、 慢查询优化的基本步骤十一、 慢日志管理一 、介绍 为何要有索引? 复杂的查询操作是我们遇到最多的也是最容易出问题的因此数据库性能的优化显然是重中之重。说起加速查询就不得不提到索引了。 什么是索引 索引在MySQL中也叫做“键”是存储引擎用于快速找到记录的一种数据结构。索引对于良好的性能非常关键表中的数据量越来越大索引对于性能的影响愈发重要。 索引能够轻易将查询性能提高好几个数量级其功能相当于字典的音序表。 3010 405 15 35 66 1 6 11 19 21 39 55 100 对索引的误解 1平衡点的选择 若索引太多应用程序的性能可能会受到影响。而索引太少对查询性能又会产生影响。 要找到一个平衡点这对应用程序的性能至关重要。 2索引优先级 开发人员编写SQL语句、存储过程之类往往对数据库的使用停留在应用的层面认为事后让相关DBA加上即可。 DBA往往不够了解业务的数据流而添加索引需要通过监控大量的SQL语句进而从中找到问题这个步骤所需的时间肯定是远大于初始添加索引所需的时间并且可能会遗漏一部分的索引。 索引的添加也是非常有技术含量的。 二 、索引的原理 一 、索引原理 索引的目的在于提高查询效率类似于查阅字典其本质都是通过不断地缩小想要获取数据的范围来筛选出最终想要的结果同时把随机的事件变成顺序的事件。 也就是说有了这种索引机制我们可以总是用同一种查找方式来锁定数据。 数据库也是一样但显然要复杂的多因为不仅面临着等值查询还有范围查询(、、between、in)、模糊查询(like)、并集查询(or)等等。 数据库应该选择怎么样的方式来应对所有的问题呢 举个例子如果1000条数据我们分成10段这样查第250条数据只要找第三段就可以了一下子去除了90%的无效数据。 但如果是1千万的记录呢 稍有算法基础的同学会想到搜索树其平均复杂度是lgN具有不错的查询性能。 但我们忽略了一个关键的问题复杂度模型是基于每次相同的操作成本来考虑的。 而数据库实现比较复杂一方面数据是保存在磁盘上的另外一方面为了提高性能每次又可以把部分数据读入内存来计算因为我们知道访问磁盘的成本大概是访问内存的十万倍左右所以简单的搜索树难以满足复杂的应用场景。 二 、磁盘IO与预读 先简单介绍一下磁盘IO和预读 磁盘读取数据靠的是机械运动每次读取数据花费的时间可以分为寻道时间、旋转延迟、传输时间三个部分 寻道时间指的是磁臂移动到指定磁道所需要的时间主流磁盘一般在5ms以下旋转延迟就是我们经常听说的磁盘转速比如一个磁盘7200转表示每分钟能转7200次也就是说1秒钟能转120次旋转延迟就是1/120/2 4.17ms传输时间指的是从磁盘读出或将数据写入磁盘的时间一般在零点几毫秒相对于前两个时间可以忽略不计。那么访问一次磁盘的时间即一次磁盘IO的时间约等于54.17 9ms左右但一台500 -MIPSMillion Instructions Per Second的机器每秒可以执行5亿条指令因为指令依靠的是电的性质换句话说执行一次IO的时间可以执行约450万条指令千万级数据的数据库每次9毫秒的时间显然是个灾难。 而磁盘IO是非常高昂的操作计算机操作系统做了一些优化当一次IO时不光把当前磁盘地址的数据而是把相邻的数据也都读取到内存缓冲区内因为局部预读性原理告诉我们当计算机访问一个地址的数据的时候与其相邻的数据也会很快被访问到。每一次IO读取的数据我们称之为一页(page)。具体一页有多大数据跟操作系统有关一般为4k或8k也就是我们读取一页内的数据时候实际上才发生了一次IO这个理论对于索引的数据结构设计非常有帮助。 三 、索引的数据结构 我们知道了索引的基本原理数据库的复杂性和操作系统的相关知识任何一种数据结构都不是凭空产生的一定会有它的背景和使用场景我们现在总结一下这种数据结构能够做些什么 数据结构每次查找数据时把磁盘IO次数控制在一个很小的数量级最好是常数数量级。那么我们就想到如果一个高度可控的多路搜索树是否能满足需求呢 就这样b树应运而生B树是通过二叉查找树再由平衡二叉树B树演化而来。 如上图是一颗b树关于b树的定义可以参见B树这里只说一些重点浅蓝色的块我们称之为一个磁盘块可以看到每个磁盘块包含几个数据项深蓝色所示和指针黄色所示如磁盘块1包含数据项17和35包含指针P1、P2、P3P1表示小于17的磁盘块P2表示在17和35之间的磁盘块P3表示大于35的磁盘块。真实的数据存在于叶子节点即3、5、9、10、13、15、28、29、36、60、75、79、90、99。非叶子节点只不存储真实的数据只存储指引搜索方向的数据项如17、35并不真实存在于数据表中。 b树的查找过程 如图所示如果要查找数据项29那么首先会把磁盘块1由磁盘加载到内存此时发生一次IO在内存中用二分查找确定29在17和35之间锁定磁盘块1的P2指针内存时间因为非常短相比磁盘的IO可以忽略不计通过磁盘块1的P2指针的磁盘地址把磁盘块3由磁盘加载到内存发生第二次IO29在26和30之间锁定磁盘块3的P2指针通过指针加载磁盘块8到内存发生第三次IO同时内存中做二分查找找到29结束查询总计三次IO。真实的情况是3层的b树可以表示上百万的数据如果上百万的数据查找只需要三次IO性能提高将是巨大的如果没有索引每个数据项都要发生一次IO那么总共需要百万次的IO显然成本非常非常高。 b树性质 1.索引字段要尽量的小我们知道IO次数取决于b数的高度h假设当前数据表的数据为N每个磁盘块的数据项的数量是m则有h㏒(m1)N当数据量N一定的情况下m越大h越小 而m 磁盘块的大小 / 数据项的大小磁盘块的大小也就是一个数据页的大小是固定的如果数据项占的空间越小数据项的数量越多树的高度越低。 这就是为什么每个数据项即索引字段要尽量的小比如int占4字节要比bigint8字节少一半。这也是为什么b树要求把真实的数据放到叶子节点而不是内层节点一旦放到内层节点磁盘块的数据项会大幅度下降导致树增高。当数据项等于1时将会退化成线性表。 2.索引的最左匹配特性当b树的数据项是复合的数据结构比如(name,age,sex)的时候b数是按照从左到右的顺序来建立搜索树的比如当(张三,20,F)这样的数据来检索的时候b树会优先比较name来确定下一步的所搜方向如果name相同再依次比较age和sex最后得到检索的数据 但当(20,F)这样的没有name的数据来的时候b树就不知道下一步该查哪个节点因为建立搜索树的时候name就是第一个比较因子必须要先根据name来搜索才能知道下一步去哪里查询。 比如当(张三,F)这样的数据来检索时b树可以用name来指定搜索方向但下一个字段age的缺失所以只能把名字等于张三的数据都找到然后再匹配性别是F的数据了 这个就是索引的最左匹配特性。 四 、聚集索引与辅助索引 在数据库中B树的高度一般都在2至4层即查找某一个键值的行记录时最多只需要2到4次IO。因为当前一般的机械硬盘每秒至少可以做100次IO2至4次的IO意味着查询时间只需要0.02~0.04秒。 数据库中的B树索引可以分为聚集索引clustered index和辅助索引secondary index 聚集索引与辅助索引相同的是不管是聚集索引还是辅助索引其内部都是B树的形式即高度是平衡的叶子结点存放着所有的数据。 聚集索引与辅助索引不同的是叶子结点存放的是否是一整行的信息 1、聚集索引 #InnoDB存储引擎表示索引组织表即表中数据按照主键顺序存放。而聚集索引clustered index就是按照每张表的主键构造一棵B树 同时叶子结点存放的即为整张表的行记录数据也将聚集索引的叶子结点称为数据页。聚集索引的这个特性决定了索引组织表中数据也是索引的一部分。 同B树数据结构一样每个数据页都通过一个双向链表来进行链接。 #如果未定义主键MySQL取第一个唯一索引unique而且只含非空列NOT NULL作为主键InnoDB使用它作为聚簇索引。 #如果没有这样的列InnoDB就自己产生一个这样的ID值它有六个字节而且是隐藏的使其作为聚簇索引。 #由于实际的数据页只能按照一棵B树进行排序因此每张表只能拥有一个聚集索引。在多少情况下查询优化器倾向于采用聚集索引。 因为聚集索引能够在B树索引的叶子节点上直接找到数据。此外由于定义了数据的逻辑顺序聚集索引能够特别快地访问针对范围值得查询。 聚集索引的好处之一它对主键的排序查找和范围查找速度非常快叶子节点的数据就是用户所要查询的数据。如用户需要查找一张表查询最后的10位用户信息由于B树索引是双向链表所以用户可以快速找到最后一个数据页并取出10条记录 聚集索引的好处之二范围查询range query即如果要查找主键某一范围内的数据通过叶子节点的上层中间节点就可以得到页的范围之后直接读取数据页即可 2、辅助索引 表中除了聚集索引外其他索引都是辅助索引Secondary Index也称为非聚集索引与聚集索引的区别是辅助索引的叶子节点不包含行记录的全部数据。 叶子节点除了包含键值以外每个叶子节点中的索引行中还包含一个书签bookmark。该书签用来告诉InnoDB存储引擎去哪里可以找到与索引相对应的行数据。 由于InnoDB存储引擎是索引组织表因此InnoDB存储引擎的辅助索引的书签就是相应行数据的聚集索引键。 如下图 辅助索引的存在并不影响数据在聚集索引中的组织因此每张表上可以有多个辅助索引但只能有一个聚集索引。当通过辅助索引来寻找数据时InnoDB存储引擎会遍历辅助索引并通过叶子级别的指针获得只想主键索引的主键然后再通过主键索引来找到一个完整的行记录。 举例来说如果在一棵高度为3的辅助索引树种查找数据那需要对这个辅助索引树遍历3次找到指定主键如果聚集索引树的高度同样为3那么还需要对聚集索引树进行3次查找最终找到一个完整的行数据所在的页因此一共需要6次逻辑IO访问才能得到最终的一个数据页。 五 、MySQL索引管理 一 、功能 索引的功能就是加速查找mysql中的primary keyunique联合唯一也都是索引这些索引除了加速查找以外还有约束的功能二 、MySQL常用的索引 普通索引INDEX加速查找唯一索引 -主键索引PRIMARY KEY加速查找约束不为空、不能重复唯一索引UNIQUE:加速查找约束不能重复联合索引PRIMARY KEY(id,name):联合主键索引UNIQUE(id,name):联合唯一索引INDEX(id,name):联合普通索引 三 、索引的两大类型hash与btree 我们可以在创建上述索引的时候为其指定索引类型分两类 hash类型的索引查询单条快范围查询慢btree类型的索引b树层数越多数据量指数级增长innodb默认支持它不同的存储引擎支持的索引类型也不一样 InnoDB 支持事务支持行级别锁定支持 B-tree、Full-text 等索引不支持 Hash 索引MyISAM 不支持事务支持表级别锁定支持 B-tree、Full-text 等索引不支持 Hash 索引Memory 不支持事务支持表级别锁定支持 B-tree、Hash 等索引不支持 Full-text 索引NDB 支持事务支持行级别锁定支持 Hash 索引不支持 B-tree、Full-text 等索引Archive 不支持事务支持表级别锁定不支持 B-tree、Hash、Full-text 等索引四 、创建/删除索引的语法 创建索引的几种操作 #方法一创建表时  CREATE TABLE 表名 (字段名1 数据类型 [完整性约束条件…], 字段名2 数据类型 [完整性约束条件…], [UNIQUE | FULLTEXT | SPATIAL ] INDEX | KEY [索引名] (字段名[(长度)] [ASC |DESC]) ); #方法二CREATE在已存在的表上创建索引 CREATE [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名 ON 表名 (字段名[(长度)] [ASC |DESC]) ; #方法三ALTER TABLE在已存在的表上创建索引 ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名 (字段名[(长度)] [ASC |DESC]) ; #删除索引DROP INDEX 索引名 ON 表名字; 举例演示 #方式一 create table t1(id int,name char,age int,sex enum(male,female),unique key uni_id(id), index ix_name(name) #index没有key ); #方式二 create index ix_age on t1(age); #方式三 alter table t1 add index ix_sex(sex); #查看 mysql show create table t1; | t1 | CREATE TABLE t1 ( id int(11) DEFAULT NULL, name char(1) DEFAULT NULL, age int(11) DEFAULT NULL, sex enum(male,female) DEFAULT NULL, UNIQUE KEY uni_id (id), KEY ix_name (name), KEY ix_age (age), KEY ix_sex (sex) ) ENGINEInnoDB DEFAULT CHARSETlatin1 六 、索引测试 一 、数据表 #1. 准备表 create table s1( id int, name varchar(20), gender char(6), email varchar(50) ); #2. 创建存储过程实现批量插入记录 delimiter $$ #声明存储过程的结束符号为$$ create procedure auto_insert1() BEGIN declare i int default 1; while(i3000000)do insert into s1 values(i,duoduo,male,concat(duoduo,i,oldboy)); set ii1; end while; END$$ #$$结束 delimiter ; #重新声明分号为结束符号 #3. 查看存储过程 show create procedure auto_insert1\G #4. 调用存储过程 call auto_insert1(); #等待时间长短看机器性能 提示创建表的时间长短看机器的性能 二 、在没有索引的前提下测试查询速度 #无索引mysql不知道是否存在id等于666的记录只能把数据表从头到尾扫描一遍此时有多少个磁盘块就需要进行多少IO操作所以查询速度很慢 mysql select * from s1 where id666; Empty set (0.27 sec) 三 、大量数据的前提下为某个字段段建立索引建立速度会很慢 四 、建立索引以该字段为查询条件时查询速度提升明显 PS mysql 先去索引表里根据b树的搜索原理很快搜索到id等于666的记录不存在IO大大降低因而速度明显提升 我们可以去mysql的data目录下找到该表可以看到占用的硬盘空间多了 需要注意如下图 五、总结 #1. 一定是为搜索条件的字段创建索引比如select * from s1 where id 666;就需要为id加上索引 #2. 大量数据的前提下建索引会很慢且占用硬盘空间建完后查询速度加快 比如create index idx on s1(id);会扫描表中所有的数据然后以id为数据项创建索引结构存放于硬盘的表中。 建完以后再查询就会很快了。 #3. 需要注意的是innodb表的索引会存放于s1.ibd文件中而myisam表的索引则会有单独的索引文件table1.MYI MySAM索引文件和数据文件是分离的索引文件仅保存数据记录的地址。 而在innodb中表数据文件本身就是按照BTreeBTree即Balance True组织的一个索引结构这棵树的叶节点data域保存了完整的数据记录。 这个索引的key是数据表的主键因此innodb表数据文件本身就是主索引。 因为inndob的数据文件要按照主键聚集所以innodb要求表必须要有主键Myisam可以没有 如果没有显式定义则mysql系统会自动选择一个可以唯一标识数据记录的列作为主键 如果不存在这种列则mysql会自动为innodb表生成一个隐含字段作为主键这字段的长度为6个字节类型为长整型. 七 、正确使用索引 一 、索引未命中 索引不一定会加快查询速度。 我们在添加索引时必须遵循以下问题 1 、范围问题 或者说条件不明确条件中出现这些符号或关键字、、、、! 、between...and...、like、 大于号、小于号 不等于 between ...and... like 2 尽量选择区分度高的列作为索引 区分度的公式是count(distinct col)/count(*)表示字段不重复的比例比例越大我们扫描的记录数越少唯一键的区分度是1而一些状态、性别字段可能在大数据面前区分度就是0 这个值很难确定一般需要join的字段我们都要求是0.1以上即平均1条扫描10条记录 先把表中的索引都删除让我们专心研究区分度的问题 #把表中的索引都删除让我们专心研究区分度的问题mysql desc s1; ------------------------------------------------ | Field | Type | Null | Key | Default | Extra | ------------------------------------------------ | id | int(11) | YES | MUL | NULL | | | name | varchar(50) | YES | | NULL | | | gender | char(5) | YES | | NULL | | | email | varchar(50) | YES | MUL | NULL | | ------------------------------------------------ 4 rows in set (0.00 sec) mysql drop index a on s1; Query OK, 0 rows affected (0.20 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql drop index d on s1; Query OK, 0 rows affected (0.18 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql desc s1; ------------------------------------------------ | Field | Type | Null | Key | Default | Extra | ------------------------------------------------ | id | int(11) | YES | | NULL | | | name | varchar(50) | YES | | NULL | | | gender | char(5) | YES | | NULL | | | email | varchar(50) | YES | | NULL | | ------------------------------------------------ 4 rows in set (0.00 sec) 分析 我们编写存储过程为表s1批量添加记录name这个字段的区分度很低gender 也是一样。 根据b树的结构查询的速度与树的高度成反比要想将树的高低控制的很低需要保证在某一层内数据项均是按照从左到右从小到大的顺序依次排开即左1左2左3... 而对于区分度低的字段因为值都是相等的无法找到大小关系毫无疑问还想要用b树存放这些等值的数据只能增加树的高度字段的区分度越低则树的高度越高。 极端的情况索引字段的值都一样那么b树几乎成了一根棍。 结论为区分度低的字段建立索引索引树的高度会很高然而这具体会带来什么影响呢 1如果条件是namexxxx,那么肯定是可以第一时间判断出xxxx是不在索引树中的因为树中所有的值均为‘duoduo’所以查询速度很快 2如果条件正好是nameduoduo,查询时我们永远无法从树的某个位置得到一个明确的范围只能往下找往下找往下找。。。这与全表扫描的IO次数没有多大区别所以速度很慢 3、和in可以乱序 比如a 1 and b 2 and c 3 建立(a,b,c)索引可以任意顺序mysql的查询优化器会帮你优化成索引可以识别的形式 4、 索引列不能参与计算保持列“干净”比如from_unixtime(create_time) ‘2018-07-12’就不能使用到索引原因很简单b树中存的都是数据表中的字段值但进行检索时需要把所有元素都应用函数才能比较显然成本太大。所以语句应该写成create_time unix_timestamp(‘2014-05-29’) 5、 and/or1、and与or的逻辑 条件1 and 条件2:所有条件都成立才算成立但凡要有一个条件不成立则最终结果不成立 条件1 or 条件2:只要有一个条件成立则最终结果就成立 2、and的工作原理 条件a 10 and b xxx and c 3 and d 4 索引制作联合索引(d,a,b,c) 工作原理:对于连续多个andmysql会按照联合索引从左到右的顺序找一个区分度高的索引字段(这样便可以快速锁定很小的范围)加速查询即按照d—a-b-c的顺序 3、or的工作原理 条件a 10 or b xxx or c 3 or d 4 索引制作联合索引(d,a,b,c) 工作原理:对于连续多个ormysql会按照条件的顺序从左到右依次判断即a-b-c-d 在左边条件成立但是索引字段的区分度低的情况下name加速查询 6 最左前缀匹配原则非常重要的原则对于组合索引mysql会一直向右匹配直到遇到范围查询(、、between、like)就停止匹配(指的是范围大了有索引速度也慢)比如a 1 and b 2 and c 3 and d 4 如果建立(a,b,c,d)顺序的索引d是用不到索引的如果建立(a,b,d,c)的索引则都可以用到a,b,d的顺序可以任意调整。 7、 其他情况 其他情况演示 - 使用函数select * from tb1 where reverse(email) duoduo; - 类型不一致 如果列是字符串类型传入条件是必须用引号引起来不然... select * from tb1 where email 999; #排序条件为索引则select字段必须也是索引字段否则无法命中 - order by select name from s1 order by email desc; 当根据索引排序时候select查询的字段如果不是索引则速度仍然很慢 select email from s1 order by email desc; 特别的如果对主键排序则还是速度很快 select * from tb1 order by nid desc; - 组合索引最左前缀 如果组合索引为(name,email) name and email -- 命中索引 name -- 命中索引 email -- 未命中索引 - count(1)或count(列)代替count(*)在mysql中没有差别了 - create index xxxx on tb(title(19)) #text类型必须制定长度 其他注意事项 - 避免使用select * - count(1)或count(列) 代替 count(*) - 创建表时尽量时 char 代替 varchar - 表的字段顺序固定长度的字段优先 - 组合索引代替多个单列索引经常使用多个条件查询时 - 尽量使用短索引 - 使用连接JOIN来代替子查询(Sub-Queries) - 连表时注意条件类型需一致 - 索引散列值重复少不适合建索引例性别不适合     转载于:https://www.cnblogs.com/yizhiamumu/p/9205568.html
http://www.zqtcl.cn/news/818341/

相关文章:

  • 网站描述标签怎么写wordpress首页图标
  • 做系统去哪个网站好好玩又不用实名认证的游戏
  • 仿帝国网站源码wordpress主题idown
  • 大型网站开发php框架seo全站优化全案例
  • wordpress收录优化做抖音seo用哪些软件
  • DW怎么做招聘网站重庆有什么好玩的
  • 网站建设的网络公司百度官方app下载
  • 医疗电子科技网站建设站群 网站如何做
  • 汇邦团建网站谁做的钢结构招聘网
  • 如何制作一个动态的网站的登录详细步骤页面网站炫酷首页
  • 网站建设找星火龙网站开发 在线支付
  • 如何在公司网站下设置邮箱自己开发一个app要多少钱
  • 珠海市横琴新区建设环保局网站做catia数据的网站
  • 珠海pc网站建设wordpress子主题安全
  • 布吉企业网站建设网站维护与建设内容
  • 专业图书商城网站建设七初SEO网站建设
  • 南通公司网站模板建站wordpress设置主页
  • 小企业网站建设哪找广州app开发平台
  • 建设部国家标准网站免费网站建设 免备案
  • 网站后台批量上传图片ue5培训机构哪家强
  • 合肥制作网站在哪里建网站
  • 网站开发话术合同管理软件系统
  • 洛阳建设网站公司vue 微信公众号开发
  • 网页的网站建设什么网站可以做免费广告
  • 秦都区建设局网站网络推广如何收费
  • 户外保险网站网站开发市场情况
  • 嘉兴企业网站排名网站快速排名服务
  • 8步快速搭建个人网站视频网站备案号被收回
  • 沈阳网站建设 景乔科技wap入口
  • 做网站服务器要用多大怎么在58建设企业的网站