第五、查询优化

1、查询慢的原因:网络因素、CPU、IO、上下文切换、系统调用、生成统计信息、锁等待时间等

2、优化数据库访问:查询性能地下的原因是访问的数据太多,某些查询不可避免的需要筛选大量的数据,可以通过减少访问数据量的方式优化;1、确认应用程序是否在检索大量超过需要的数据;2、确认mysql服务器层是否在分析大量超过需要的数据行

3、执行过程优化:

1、查询缓存:在解析一个查询语句之前,如果查询缓存是打开的,那么mysql会优先检查这个查询是否命中查询缓存中的数据,如果查询恰好命中了查询缓存,那么会在返回结果之前会检查用户权限,如果权限没有问题,那么mysql会跳过所有的阶段,就直接从缓存中拿到结果并返回给客户端;

2、查询优化处理:mysql查询完缓存之后会经过以下几个步骤:解析SQL、预处理、优化SQL执行计划,这几个步骤出现任何的错误,都可能会终止查询;

1、语法解析器和预处理:mysql通过关键字将SQL语句进行解析,并生成一颗解析树,mysql解析器将使用mysql语法规则验证和解析查询,例如验证使用使用了错误的关键字或者顺序是否正确等等,预处理器会进一步检查解析树是否合法,例如表名和列名是否存在,是否有歧义,还会验证权限等等

2、查询优化器:

1、select count(*) from table;show status like 'last_query_cost'; 可以看到这条查询语句大概需要做1104个数据页才能找到对应的数据,这是经过一系列的统计信息计算来的(每个表或者索引的页面个数;索引的基数;索引和数据行的长度;索引的分布情况)

2、很多时候mysql会选择错误的执行计划(统计信息不准确(InnoDB因为其mvcc的架构,并不能维护一个数据表的行数的精确统计信息

);执行计划的成本估算不等同于实际执行的成本(有时候某个执行计划虽然需要读取更多的页面,但是他的成本却更小,因为如果这些页面都是顺序读或者这些页面都已经在内存中的话,那么它的访问成本将很小,mysql层面并不知道哪些页面在内存中,哪些在磁盘,所以查询之际执行过程中到底需要多少次IO是无法得知的);mysql的最优可能跟你想的不一样(mysql的优化是基于成本模型的优化,但是有可能不是最快的优化);mysql不考虑其他并发执行的查询;mysql不会考虑不受其控制的操作成本(执行存储过程或者用户自定义函数的成本));

3、优化器的优化策略:1、静态优化,直接对解析树进行分析,并完成优化;2、动态优化,动态优化与查询的上下文有关,也可能跟取值、索引对应的行数有关;3、mysql对查询的静态优化只需要一次,但对动态优化在每次执行时都需要重新评估

4、优化器的优化类型:重新定义关联表的顺序(数据表的关联并不总是按照在查询中指定的顺序进行,决定关联顺序时优化器很重要的功能);将外连接转化为内连接,内连接的效率要高于外连接;使用等价变换规则,mysql可以使用一些等价变化来简化并规划表达式;优化count、min、max索引和列是否可以为空通常可以帮助mysql优化这类表达式:例如,要找到某一列的最小值,只需要查询索引的最左端的记录即可,不需要全文扫描比较;预估并转化为常数表达式,当mysql检测到一个表达式可以转化为常数的时候,就会一直把该表达式作为常数进行处理;索引覆盖扫描,当索引中的列包含所有查询中需要使用的列的时候,可以使用覆盖索引;子查询优化,mysql在某些情况下可以将子查询转换一种效率更高的形式,从而减少多个查询多次对数据进行访问,例如将经常查询的数据放入到缓存中;等值传播:如果两个列的值通过等式关联,那么mysql能够把其中一个列的where条件传递到另一个上:explain select film.film_id from film inner join film_actor using(film_id) where film.film_id > 500;这里使用film_id字段进行等值关联,film_id这个列不仅适用于film表而且适用于film_actor表explain select film.film_id from film inner join film_actor using(film_id) where film.film_id > 500 and film_actor.film_id > 500;

3、关联查询:join的实现原理,Simple Nested-Loop Join,r表示驱动表、s表示驱动表,从图中可以看出从r中拿到数据匹配s开销很大

Index Nested-Loop Join要求非驱动表上有索引,可以通过索引来减少比较,加速查询;在查询时,驱动表(r)会根据关联字段的索引进行查询,当在索引上找到符合的值,在进行回表查询

Block Nested-Loop Join如果有索引会选取第二种方式进行join如果没有索引才会使用Block Nested-Loop Join;

(1)Join Buffer会缓存所有参与查询的列而不是只有Join的列。

(2)可以通过调整join_buffer_size缓存大小

(3)join_buffer_size的默认值是256K,join_buffer_size的最大值在MySQL 5.1.22版本前是4G-1,而之后的版本才能在64位操作系统下申请大于4G的Join Buffer空间。

(4)使用Block Nested-Loop Join算法需要开启优化器管理配置的optimizer_switch的设置block_nested_loop为on,默认为开启。

show variables like '%optimizer_switch%'

4、排序优化:无论如何排序都是一个成本很高的操作,所以从性能的角度出发,应该尽可能避免排序或者尽可能避免对大量数据进行排序。

推荐使用利用索引进行排序,但是当不能使用索引的时候,mysql就需要自己进行排序,如果数据量小则再内存中进行,如果数据量大就需要使用磁盘,mysql中称之为filesort。如果需要排序的数据量小于排序缓冲区(show variables like '%sort_buffer_size%';),mysql使用内存进行快速排序操作,如果内存不够排序,那么mysql就会先将树分块,对每个独立的块使用快速排序进行排序,并将各个块的排序结果存放再磁盘上,然后将各个排好序的块进行合并,最后返回排序结果。

排序算法:两次传值排序,第一次数据读取是将需要排序的字段读取出来,然后进行排序,第二次是将排好序的结果按照需要去读取数据行。

这种方式效率比较低,原因是第二次读取数据的时候因为已经排好序,需要去读取所有记录而此时更多的是随机IO,读取数据成本会比较高

两次传输的优势,在排序的时候存储尽可能少的数据,让排序缓冲区可以尽可能多的容纳行数来进行排序操作。单次传输排序:先读取查询所需要的所有列,然后再根据给定列进行排序,最后直接返回排序结果,此方式只需要一次顺序IO读取所有的数据,而无须任何的随机IO,问题在于查询的列特别多的时候,会占用大量的存储空间,无法存储大量的数据。当需要排序的列的总大小超过max_length_for_sort_data定义的字节,mysql会选择双次排序,反之使用单次排序,当然,用户可以设置此参数的值来选择排序的方式。

4、优化特定类型的优化:

1、优化count查询:没有where条件时,count(*)才是最快的,在myisam的count中;使用近似值,在某些应用场景中,不需要完全精确的值,可以参考使用近似值来代替,比如可以使用explain来获取近似的值;其实在很多OLAP的应用中,需要计算某一个列值的基数,有一个计算近似值的算法叫hyperloglog。更复杂的优化:一般情况下,count()需要扫描大量的行才能获取精确的数据,其实很难优化,在实际操作的时候可以考虑使用索引覆盖扫描,或者增加汇总表,或者增加外部缓存系统。

2、优化关联查询:确保on或者using子句中的列上有索引,在创建索引的时候就要考虑到关联的顺序,当表A和表B使用列C关联的时候,如果优化器的关联顺序是B、A,那么就不需要再B表的对应列上建上索引,没有用到的索引只会带来额外的负担,一般情况下来说,只需要在关联顺序中的第二个表的相应列上创建索引。确保任何的groupby和order by中的表达式只涉及到一个表中的列,这样mysql才有可能使用索引来优化这个过程。

3、优化子查询:子查询的优化最重要的优化建议是尽可能使用关联查询代替

4、优化limit分页:在很多应用场景中我们需要将数据进行分页,一般会使用limit加上偏移量的方法实现,同时加上合适的orderby 的子句,如果这种方式有索引的帮助,效率通常不错,否则的化需要进行大量的文件排序操作,还有一种情况,当偏移量非常大的时候,前面的大部分数据都会被抛弃,这样的代价太高。要优化这种查询的话,要么是在页面中限制分页的数量,要么优化大偏移量的性能。(优化此类查询的最简单的办法就是尽可能地使用覆盖索引,而不是查询所有的列);

5、优化union查询:mysql总是通过创建并填充临时表的方式来执行union查询,因此很多优化策略在union查询中都没法很好的使用。经常需要手工的将where、limit、order by等子句下推到各个子查询中,以便优化器可以充分利用这些条件进行优化;除非确实需要服务器消除重复的行,否则一定要使用union all,因此没有all关键字,mysql会在查询的时候给临时表加上distinct的关键字,这个操作的代价很高。

第六、分区表

1、分区表应用场景:表非常大以至于无法全部都放在内存中,或者只在表的最后部分有热点数据,其他均是历史数据;分区表的数据更容易维护(批量删除大量数据可以使用清除整个分区的方式;对一个独立分区进行优化、检查、修复等操作);分区表的数据可以分布在不同的物理设备上,从而高效地利用多个硬件设备;可以使用分区表来避免某些特殊的瓶颈(innodb的单个索引的互斥访问;ext3文件系统的inode锁竞争);可以备份和恢复独立的分区。

2、分区表的权限:一个表最多只能有1024个分区,在5.7版本的时候可以支持8196个分区;在早期的mysql中,分区表达式必须是整数或者是返回整数的表达式,在mysql5.5中,某些场景可以直接使用列来进行分区;如果分区字段中有主键或者唯一索引的列,那么所有主键列和唯一索引列都必须包含进来;分区表无法使用外键约束。

3、分区表原理:分区表由多个相关的底层表实现,这个底层表也是由句柄对象标识,我们可以直接访问各个分区。存储引擎管理分区的各个底层表和管理普通表一样(所有的底层表都必须使用相同的存储引擎),分区表的索引知识在各个底层表上各自加上一个完全相同的索引。从存储引擎的角度来看,底层表和普通表没有任何不同,存储引擎也无须知道这是一个普通表还是一个分区表的一部分。

**select查询**

当查询一个分区表的时候,分区层先打开并锁住所有的底层表,优化器先判断是否可以过滤部分分区,然后再调用对应的存储引擎接口访问各个分区的数据

**insert操作**

当写入一条记录的时候,分区层先打开并锁住所有的底层表,然后确定哪个分区接受这条记录,再将记录写入对应底层表

**delete操作**

当删除一条记录时,分区层先打开并锁住所有的底层表,然后确定数据对应的分区,最后对相应底层表进行删除操作

4、分区表类型:范围分区;列表分区;列分区;hash分区;key分区;子分区。

5、如何使用分区表:全量扫描数据,不要任何索引,使用简单的分区方式存放表,不要任何索引,根据分区规则大致定位需要的数据为止,通过使用where条件将需要的数据限制在少数分区中,这种策略适用于以正常的方式访问大量数据;索引数据,并分离热点,如果数据有明显的热点,而且除了这部分数据,其他数据很少被访问到,那么可以将这部分热点数据单独放在一个分区中,让这个分区的数据能够有机会都缓存在内存中,这样查询就可以只访问一个很小的分区表,能够使用索引,也能够有效的使用缓存。

第七八章我还需要再学习先去看看官网

mysql 关联查询_mysql数据库调优(二)相关推荐

  1. mysql客户端查询_MySQL数据库之利用mysql客户端查询UCSC数据库

    本文主要向大家介绍了MySQL数据库之利用mysql客户端查询UCSC数据库 ,通过具体的内容向大家展现,希望对大家学习MySQL数据库有所帮助. UCSC Genome Browser是由Unive ...

  2. mysql 关联查询_Mysql查询优化器,再也不会因为该什么时候建立索引发愁了

    优化器的作用: 我们知道,一条SQL语句,可以有很多执行方式,最后都返回相同的结果,而优化器的作用就是找到最好的执行计划. 一.RBO-基于规则的优化器(rule) 系统内置的一套硬编码规则,根据规则 ...

  3. 艺赛旗(RPA)Mysql 数据查询慢 - 索引调优 Explain 用法

    艺赛旗 RPA8.0全新首发免费下载 点击下载 http://www.i-search.com.cn/index.html?from=line1 在日常工作中,我们会有时会开慢查询去记录一些执行时间比 ...

  4. mysql数据库做关联查询_mysql 数据库join关联查询using(xxx)的作用

    user表: id | name --------- 1 | libk 2 | zyfon 3 | daodao user_action表: user_id | action ------------ ...

  5. mysql 优化器关联查询_MySQL 查询优化器(二)

    1.6多个查询字段(常量条件) 多个查询字段的查询处理逻辑如下所示: JOIN:prepare阶段 setup_tables():同1.1测试. setup_fields():同1.1测试. setu ...

  6. mysql 回退查询_MYSQL数据库表排序规则不一致导致联表查询,索引不起作用问题...

    Mysql数据库表排序规则不一致导致联表查询,索引不起作用问题 表更描述: 将mysql数据库中的worktask表添加ishaspic字段. 具体操作:(1)数据库worktask表新添是否有图片字 ...

  7. mysql 回退查询_MySQL数据库:第十章:分页查询

    引入:实际的开发时,一页往往显示不全所有数据,则用到了分页查询 语法: select 查询列表 ⑥ from 表 ① [join 表 ② on 连接条件 ③ where 筛选 ④ group by 分 ...

  8. mysql离散查询_mySQL数据库数据查询操作详解

    查询数据: 简单查询: 1.查询所有数据: select * from 表名 #select * from info 查询所有列 2.查询指定列: select code,name from info ...

  9. mysql数据库调优知识复习

    mysql数据库调优基本上是面试必问的,不过平时工作中用的还是有点偏少,容易忘记,还是记录一下,时常可以看看,今天时间不充足了,暂且写一点,然后在不断补充 1.慢查询优化 1).检查慢查日志是否开启: ...

最新文章

  1. 批量显示JOB Log
  2. 条形图坐标轴_手把手教你用Excel绘图 | 双轴簇状条形图
  3. OpenCASCADE:简介
  4. 3-18pytorch与矩阵分解PCA
  5. JAVA提取字符串信息中的数字(包括整数,小数)工具类
  6. MonoRail学习笔记十七:TransformFilter的使用
  7. Ubuntu16.04安装QQ(for linux)
  8. 奥维互动地图恢复旧版及导入谷歌卫星图
  9. 如何删除在System中打开的iso文件
  10. [11] 微信公众帐号开发教程第11篇-符号表情的发送(上)
  11. 22-04-23 西安 javaSE(14)文件流、缓冲流、转换流、对象流、标准流、关闭IO资源的封装类IOUtils(纳命来)
  12. 技术分享 | 无人机仿真教程-Prometheus平台 -转自阿木实验室
  13. 武田宣布多项细胞疗法合作,以推进公司的新型免疫肿瘤学阵容
  14. MAC OSX 终端添加代理
  15. 域格9x07模块问题日志抓取方法
  16. 关于zIndex的问题
  17. mac安装mongodb数据库
  18. js实现图片在div内滚轮放大缩小,有滚动条,双击回原状
  19. 投影参数_购买家用投影仪主要看什么参数?
  20. 程序设计与算法三~C++面向对象程序设计~北大郭炜MOOC学习笔记chapter1第一章(新标准C++程序设计)

热门文章

  1. Android调用binder实现权限提升-android学习之旅(81)
  2. Qt5:渐变效果的实现
  3. 操作系统学习笔记-06-系统调用
  4. Windows 程序设计技巧
  5. 计算机组成原理——总线系统总结
  6. 数据卡片_VISA消息:关于VCPS 2.1卡片产品的性能和交叉测试的卡片个性化数据的更新...
  7. 机器人 蓝buff 钩_机器人要在S赛登场了?Ming韩服练起来了,这是RNG黑科技?
  8. Error:collect2:ld returned 1 exit status的其他原因
  9. feign 整合sentinel_SpringCloud实战五-Sentinel上
  10. mysql 启动 修改密码_基础的启动/停止/重启/密码修改MySQL