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

第五、查询优化

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开销很大

91dbec683d0be50f6b6bfd1e737b5975.png

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

8eab87fd50f101dd7b16a4b0cd51f41f.png

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%'

eef6721986b3a80b529e76a57c0e8e3f.png

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条件将需要的数据限制在少数分区中,这种策略适用于以正常的方式访问大量数据;索引数据,并分离热点,如果数据有明显的热点,而且除了这部分数据,其他数据很少被访问到,那么可以将这部分热点数据单独放在一个分区中,让这个分区的数据能够有机会都缓存在内存中,这样查询就可以只访问一个很小的分区表,能够使用索引,也能够有效的使用缓存。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/501303.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux连接xshell时连不上的问题【转载】

最近这一周由于自己的xshell突然连接不到虚拟机,在网上找了很多种方法也没能解决,以至于自己在学习很多知识的时候都没能很好的去验证,去尝试。最后在求助大佬的时候终于将xshell重新连接到了虚拟机!! 以下是我对xshel…

Linux的实际操作:关机shutdown、重启reboot、用户注销logout

1.关机和重启命令 (1)shutdown :shutdown -h now(立即关机) 、shutdown -h 1(1分钟后关机)、shutdown -r now(立即重启) (2)halt:直接使用,效果等价于关机 (3)reboot&…

sql 一列中平均应发工资_劳动者的工资标准,应如何认定?

工资是指劳动者付出体力或脑力劳动后所得的对价,体现的是劳动者创造的社会价值。自我国劳动争议仲裁制度建立以来,工资(劳动报酬)争议一直是劳动争议的热点。如何准确把握工资标准的认定,对维护劳动者合法权益、构建和谐稳定的劳动关系具有重…

Linux的实际操作:用户管理(用户添加useradd -d和设置用户密码passwd)

Linux创作者对于用户管理主要体现在两个方面 1.将用户存放到不同的组去进行管理,一个用户可以放在不同的组 2.用户具有“家”目录的概念,当用户登录时,会自动进入到自己的家目录(/home) 例如:/home/user1…

配置了坐标还是找不到serv_你那么努力,为何还是找不到工作?从优势发展观来看个人职业发展...

扬子的大学专业是金融学,因为父母说学金融有前途,但扬子从小动手能力强,喜欢的是机械设计,因此他在大学期间还辅修了机械工程专业,大二的时候参加过一场业内的机械设计比赛还获得了二等奖,要知道一起参加比…

Linux如何查看所有用户和用户组信息(cat groups whoami)

1.cat /etc/passwd查看所有的用户信息 concatenate files and print on the standard output把文件连接后输出到屏幕上 cat /etc/passwd怎么看呢? 第一个user3是用户名,x是密码, 1002是用户id, 1002是用户组id, /home…

verilog 浮点转定点_定点数和浮点数

定点数定点数是指,数字在小数点之后和之前具有固定的位数。可以用Qm.n表示法进行表示.m位为整数部分 n位小数部分有符号数的总位数N m n 1当n0时,则定点数用来存储整数。定点数(整数)定点数可以用来存储整数,包括正整数和负整数。定点(整数…

Linux的实际操作:用户管理(删除用户userdel userdel -r)

首先需要查看当前有哪些用户 方法1: cat /etc/passwd 方法2: cd /home/ ll第一种删除(温柔式-保留家目录) userdel 用户名 (首先,保证在root用户的前提下去删除) 观察删除后的变化 第二种…

Linux的实际操作:查询用户id切换用户su -

1.查询用户信息:其中 (uid是用户的id号,gid是用户组的id号,属于哪个组) id 用户名 如果没有此用户,控制台就会返回信息“no such user” 2.切换用户: 在Linux操作中,如果当前的用户…

哔哩哔哩公司swot分析_「127」一个简单的工具分析自己的优势与劣势

今天要介绍的就是---SWOT分析方法。何谓SWOT,SWOT是由优势(Strength)、劣势(Weakness)、机会(Opportunity)和威胁(Threat)四个单词的第一个字母组成。SWOT分析是对组织或个人内外部条件各方面内容进行综合和概括,进而分析组织或个人的优劣势、面临的机会…

Linux的实际操作:用户管理(用户组的管理groupadd useradd usermod)

1.类似于管理角色,系统可以有共性的多个用户 2.增加一个用户组usergroup4 groupadd 新的用户组名 将user4指定到usergroup4中 useradd -g 用户组名 用户名 演示: 3.修改用户组 usermod -g 修改到的用户组名 用户名 创建一个usergroup5的用户组 将…

Linux的实际操作:用户管理(查看用户和组的配置文件/etc/passwd /etc/group /etc/shadow)

用户和用户组的相关文件 我们可以这样去理解,用户和用户组其实是我们虚构出来的东西,那这些东西肯定需要一个空间来存放他们吧,这个空间就是一些配置文件,里面可以完全查看你的用户或者用户组的信息,有些不过是进行了一…

拦截游戏窗口被移动_「维维足球pro-教案」50个传控踢法练习之(一、二)追球游戏...

如图所示,上方黄色虚线代表球的移动,中间黑色实线代表球员移动,下方黑色虚曲线代表球员带球移动。术语:卡斯特球员(kaasters):荷兰语“回传”。指站在指定地点,在一或两次触球内接到传球并回传的球员。(即进…

Linux的实际操作:文件目录类的实用指令(init运行级别和找回root密码)

1.介绍运行级别 设计者把Linux系统设置为7个级别,常用的运行级别是3:(程序员)和5:(普通访问用户),就好像Windows系统杀毒的时候会进入到安全模式一样 0:关机 1:单用户【用于找回丢…

linux内核怎么修改屏幕旋转方向_运维必备:常见的Linux系统故障及其排查的方法...

Linux是当前市场上比较常用的、自由开源操作系统,也是云计算运维人员日常工作中的好帮手。不过很多初学云计算的小伙伴面对Linux系统出现的故障束手无策,接下来千锋广州云计算培训小编就给大家分享几个常见的Linux系统故障及其排查的方法。​1、root密码…

Linux的实际操作:文件目录类的实用指令(帮助指令 man help)

1.人的脑容量有限,需要记忆很多东西,当我们对某个指令不熟悉时,这时候可以通过Linux简单的帮助指令就可以查询到该指令的使用方法 man 获得帮助信息 基本语法:(记忆为,有问题找男人) man ls 通…

json最大长度限制_api接口返回动态的json格式?我太难了,尝试一下 linq to json

一:背景1. 讲故事前段时间和一家公司联调api接口的时候,发现一个奇葩的问题,它的api返回的json会动态改变,简化如下:{"Code":101,"Items":[{"OrderTitle":"订单1"}]}{"C…

Linux的实际操作:文件目录类的实用指令 (显示路径pwd 显示文件ls 更改目录cd)

文件目录类的相关指令汇总:(后续会有更新) 1.pwd指令 pwd 功能:显示当前工作目录的绝对路径 2.ls指令 ls ls 横向排列出所有不隐藏的文件与文件夹 ls -l ls -l 以列表的方式显示不隐藏的文件与文件夹的详细信息 ls -a ls -a…

前端wxml取后台js变量值_微信小程序云开发教程WXML入门数据绑定

同学们大家好,我是小伊同学,今天带领大家学习WXML部分一个重要的知识点,数据绑定。简单来讲,数据绑定就是通过双重花括号将一个变量绑定到界面上。首先,我们为什么要将变量绑定到页面上呢?因为在制作一个小…

Linux的实际操作:文件目录类的实用指令(创建目录mkdir 删除目录rmdir 递归删除目录rm -rf)

有时候我们会发现,Linux自带的层级结构的目录就那么几个,但是我们日常使用中不可能就这么几个而已,因此我们还需要主动去创建目录,相当于在原有路径的基础上,创建目录,这个目录值得是文件夹 1.mkdir 目录 …