mysql not in优化_实践中如何优化MySQL(收藏)

  • SQL语句的优化:
    • 1、尽量避免使用子查询
    • 3、用IN来替换OR
    • 4、LIKE前缀%号、双百分号、_下划线查询非索引列或*无法使用到索引,如果查询的是索引列则可以
    • 5、读取适当的记录LIMIT M,N,而不要读多余的记录
    • 6、避免数据类型不一致
    • 7、分组统计可以禁止排序sort,总和查询可以禁止排重用union all
    • 8、避免随机取记录
    • 9、禁止不必要的ORDER BY排序
    • 10、批量INSERT插入
    • 11、不要使用NOT等负向查询条件
    • 12、尽量不用select *
    • 13、**区分in和exists**
  • 索引的优化:
    • 1、Join语句的优化
    • 2、避免索引失效

在开始介绍如何优化sql前,先附上mysql内部逻辑图让大家有所了解

860c12e6e418486180300fee3beb9c8a.png

① SQL语句及索引的优化

SQL语句的优化:

1、尽量避免使用子查询

af93338c3d5395f644c79dc80129c619.png

2、避免函数索引

aff62c04294d76d79a994cd7b0366b33.png

3、用IN来替换OR

a3b519fb7d3b97058914d506eb1c5ea2.png

另外,MySQL对于IN做了相应的优化,即将IN中的常量全部存储在一个数组里面,而且这个数组是排好序的。但是如果数值较多,产生的消耗也是比较大的。再例如:select id from table_name where num in(1,2,3) 对于连续的数值,能用 between 就不要用 in 了;再或者使用连接来替换。

4、LIKE前缀%号、双百分号、_下划线查询非索引列或*无法使用到索引,如果查询的是索引列则可以

1413f49eb69ea5e281062e3fdae57033.png

5、读取适当的记录LIMIT M,N,而不要读多余的记录

select id,name 
from table_name limit 866613, 20

使用上述sql语句做分页的时候,可能有人会发现,随着表数据量的增加,直接使用limit分页查询会越来越慢。

优化的方法如下:可以取前一页的最大行数的id,然后根据这个最大的id来限制下一页的起点。比如此列中,上一页最大的id是866612。sql可以采用如下的写法:

select id,name from table_name 
where id> 866612 limit 20

6、避免数据类型不一致

7、分组统计可以禁止排序sort,总和查询可以禁止排重用union all

fa304d8c903873c8bda43630dfa8a299.png

union和union all的差异主要是前者需要将结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的CPU运算,加大资源消耗及延迟。**当然,union all的前提条件是两个结果集没有重复数据。**所以一般是我们明确知道不会出现重复数据的时候才建议使用 union all 提高速度。

另外,如果排序字段没有用到索引,就尽量少排序;

8、避免随机取记录

c7069b9c50dcb06cd4671d627d79ea83.png

9、禁止不必要的ORDER BY排序

0825f065687217f2222437c72a551df8.png

10、批量INSERT插入

caf75b167afc8a378d770e87d5e67565.png

11、不要使用NOT等负向查询条件

你可以想象一下,对于一棵B+树,根节点是40,如果你的条件是等于20,就去左面查,你的条件等于50,就去右面查,但是你的条件是不等于66,索引应该咋办?还不是遍历一遍才知道。

12、尽量不用select *

SELECT *增加很多不必要的消耗(cpu、io、内存、网络带宽);增加了使用覆盖索引的可能性;当表结构发生改变时,前者也需要经常更新。所以要求直接在select后面接上字段名。

13、区分in和exists

select * from 表A 
where id in (select id from 表B)

上面sql语句相当于

select * from 表A 
where exists(select * from 表B where 表B.id=表A.id)

区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询。所以IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。

索引的优化:

1、Join语句的优化

Join 性能点

当我们执行两个表的Join的时候,就会有一个比较的过程,逐条比较两个表的语句是比较慢的,因此可以把两个表中数据依次读进一个内存块中,在Mysql中执行:show variables like 'join_buffer_size',可以看到join在内存中的缓存池大小,其大小将会影响join语句的性能。

在执行join的时候,数据库会选择一个表把他要返回以及需要进行和其他表进行比较的数据放进join_buffer。

如果是有索引的情况,则直接读取两个表的索引树进行比较就可以了。

若没有索引,则会使用 'Block nested loop' 算法,Block 块,也就是说每次都会取一块数据到内存以减少I/O的开销

72fec4d263281bd1d169dfaad497740b.png

另外,Innodb会为每个数据表分配一个存储在磁盘的 表名.ibd 文件,若关联的表过多,将会导致查询的时候磁盘的磁头移动次数过多,从而影响性能

所以实践中,尽可能减少Join语句中的NestedLoop的循环次数:“永远用小结果集驱动大的结果集”

  1. 用小结果集驱动大结果集,将筛选结果小的表首先连接,再去连接结果集比较大的表,尽量减少join语句中的Nested Loop的循环总次数
  2. 优先优化Nested Loop的内层循环(也就是最外层的Join连接),因为内层循环是循环中执行次数最多的,每次循环提升很小的性能都能在整个循环中提升很大的性能;
  3. 对被驱动表的join字段上建立索引
  4. 当被驱动表的join字段上无法建立索引的时候,设置足够的Join Buffer Size
  5. 尽量用inner join(因为其会自动选择小表去驱动大表).避免 LEFT JOIN (一般我们使用Left Join的场景是大表驱动小表)和NULL,那么如何优化Left Join呢?
    1、条件中尽量能够过滤一些行将驱动表变得小一点,用小表去驱动大表
    2、右表的条件列一定要加上索引(主键、唯一索引、前缀索引等),最好能够使type达到range及以上(ref,eq_ref,const,system)
  6. 适当地在表里面添加冗余信息来减少join的次数
  7. 使用更快的固态硬盘

性能优化,left join 是由左边决定的,左边一定都有,所以右边是我们的关键点,建立索引要建在右边。当然如果索引是在左边的,我们可以考虑使用右连接,如下

select * from atable
left join btable on atable.aid=btable.bid;//最好在bid上建索引

(Tips:Join左连接在右边建立索引;组合索引则尽量将数据量大的放在左边,在左边建立索引)

2、避免索引失效

1.最佳左前缀法则

如果索引了多列,要遵守最左前缀法则,指的是查询从索引的最左前列开始并且不跳过索引中的列。Mysql查询优化器会对查询的字段进行改进,判断查询的字段以哪种形式组合能使得查询更快,所有比如创建的是(a,b)索引,查询的是(b,a),查询优化器会修改成(a,b)后使用索引查询。

2.不在索引列上做任何操作

(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描。

3.存储引擎不能使用索引中范围条件右边的列。

如这样的sql: select * from user where username='123' and age>20 and phone='1390012345',其中username, age, phone都有索引,只有username和age会生效,phone的索引没有用到。

4.尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致))

select age from user减少`select *``

5.mysql在使用不等于(!= 或者 <>)的时候无法使用索引会导致全表扫描。

6.is null, is not null 也无法使用索引,在实际中尽量不要使用null。

7.like 以通配符开头(‘%abc..’)mysql索引失效会变成全表扫描的操作。

所以最好用右边like 'abc%'。如果两边都要用,可以用select age from user where username like '%abc%',其中age是必须是索引列,才可让索引生效

假如index(a,b,c), where a=3 and b like 'abc%' and c=4,a能用,b能用,c不能用,类似于不能使用范围条件右边的列的索引

对于一棵B+树来讲,如果根是字符def,如果通配符在后面,例如abc%,则应该搜索左面,例如efg%,则应该搜索右面,如果通配符在前面%abc,则不知道应该走哪一面,还是都扫描一遍吧。

8.字符串不加单引号索引失效

9.少用or,用它来连接时会索引失效

10.尽量避免子查询,而用join

11、在组合索引中,将有区分度的索引放在前面

如果没有区分度,例如用性别,相当于把整个大表分成两部分,查找数据还是需要遍历半个表才能找到,使得索引失去了意义。

12、避免在 where 子句中对字段进行 null 值判断

对于null的判断会导致引擎放弃使用索引而进行全表扫描。

② 数据库表结构的优化:使得数据库结构符合三大范式与BCNF

③ 系统配置的优化

④ 硬件的优化

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

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

相关文章

java 鼠标精灵_纯Java实现跨平台鼠标键盘模拟、找图找色,Java版按键精灵

由原本的Java使用JNI调用dll实现模拟辅助操作&#xff0c;升级到纯Java来实现&#xff0c;最新&#xff1a; https://github.com/xnx3/xnx31.[代码][Java]代码/*** 鼠标、键盘、延迟等基本操作*/public static void simple(){Robot robot new Robot();robot.delay(1000); //延…

o2oa二次开发比开发难吗_6年经验大牛,带你一起打开 Revit 二次开发的新世界大门...

​知乎视频​www.zhihu.com你好&#xff0c;这里是BIMBOX。一线的BIM工作者使用最多的软件是Revit&#xff0c;它功能强大&#xff0c;涵盖建筑、结构、MEP等专业&#xff0c;也正因为涵盖专业太多&#xff0c;它显得有点繁琐和笨拙&#xff0c;不仅约束了创造力&#xff0c;有…

java的迭代器类中有哪些类_java中的集合类 以及 迭代器

/*java中的集合类 实现了 Connection接口ArrayList这个集合类 java.util.*这个包的类toArray()方法可以返回一个 Object类型的对象数组我们部队 ArratList进行泛型规范那么就会警告 但是还是可以运行的这是因为JDK1.5中引进了泛型&#xff0c;但是你的ArrayList却没有采用&a…

python计算圆柱体体积代码_继承实现圆柱体面积体积的计算

一&#xff0e;编写一个圆类Circle&#xff0c;该类拥有&#xff1a;①一个成员变量Radius// 存放圆的半径&#xff1b;私有&#xff0c;浮点型②两个构造方法Circle( ) // 将半径设为0Circle(doubler ) //创建Circle对象时将半径初始化为r③三个成员方…

python spider怎么用_python爬虫入门(七)Scrapy框架之Spider类

Spider类Spider类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。换句话说&#xff0c;Spider就是您定义爬取的动作及分析某个网页(或者是有些网页)的地方。class scrapy.Spider是最基本的类&#xff0…

mysql5.7 存储二进制_mysql5.7二进制部署

1.解压及创建目录[roothadoop39 local]# tar xzvf mysql-5.7.11-linux-glibc2.5-x86_64.tar.gz[roothadoop39 local]# mv mysql-5.7.11-linux-glibc2.5-x86_64 mysql[roothadoop39 local]# mkdir mysql/arch mysql/data mysql/tmp2.创建my.cnf(见文件)[roothadoop39 local]# vi…

ctypes python3.7_装新的python3.7时ModuleNotFoundError: No module named '_ctypes'

在编译安装新的python3.7的时候报错 ModuleNotFoundError: No module named _ctypes&#xff0c;其实是缺少了一个新需要的开发包libffi-devel&#xff0c;安装后即可yum install libffi-devel -y (包在base)最终显示Installing collected packages: setuptools, pipSuccessful…

python中的str方法和repr方法_Python中 的 __str__ 方法和 __repr__ 方法的区别有哪些

Python中 的 __str__ 方法和 __repr__ 方法的区别有哪些发布时间&#xff1a;2020-11-05 17:11:48来源&#xff1a;亿速云阅读&#xff1a;95作者&#xff1a;Leah本篇文章给大家分享的是有关Python中 的 __str__ 方法和 __repr__ 方法的区别有哪些&#xff0c;小编觉得挺实用的…

requestbody前端怎么传_学习前端开发前的基础知识了解「V1001」

一、什么是http协议?什么是协议&#xff0c;就是一群人协商好了&#xff0c;统一认知的规则。【例】你&#xff0c;我&#xff0c;他&#xff0c;还有她他他&#xff0c;大家一致认定结婚的时候都要给份子钱&#xff0c;这种大家认同的就是协议。http协议&#xff0c;就规定了…

postmapping注解参数说明_从零搭建后端框架:优雅的参数校验Validator

前两天项目群里发生了关于参数校验的问题讨论&#xff0c;很多开发团队没有对这些做硬性规范时&#xff0c;还是有很多童鞋本着“不多事”的原则&#xff0c;产品文档里没有特别说明就不写。对于2B的产品经理来说&#xff0c;因为一次新迭代&#xff0c;可能回涉及到N多的页面&…

java竖线分割_Java String类的Split以竖线作为分隔符

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请写明出处。https://blog.csdn.net/wo541075754/article/details/50668160问题Java中String类的Split方法&#xff0c;当用“|”进行分割时&#xff0c;发现并不能达到预期的效果。比如&#xff1a;分割字符串“ABC|DE…

ups计算软件_浅析UPS与蓄电池与逆变器的区别

早期的电信机房中&#xff0c;通常采用将220V交流电源经过整流&#xff0c;为48V电池组充电&#xff0c;由电池组直接给程控交换机供电。随着计算机网络和通信网络在电信机房的应用&#xff0c;需要为其提供高质量的220V的交流电源。由于有现有的48V电池组&#xff0c;所以通常…

java字符转为数字_Java 判断字符串能否转化为数字的三种方法

linux shell 常用指令1. man 对你熟悉或不熟悉的命令提供帮助解释 eg:man ls 就可以查看ls相关的用法 注:按q键或者ctrlc退出,在linux下可以使用ctrlc终止当前程序运行. 2. ls 查看目 ...在uwp中复活常用的vb库函数这个博文是纯原创的,转载一定要说明作者是 Nukepayload2!! 在.…

python调用gpu进行运算_tensorflow指定CPU与GPU运算的方法实现

1.指定GPU运算如果安装的是GPU版本&#xff0c;在运行的过程中TensorFlow能够自动检测。如果检测到GPU&#xff0c;TensorFlow会尽可能的利用找到的第一个GPU来执行操作。如果机器上有超过一个可用的GPU&#xff0c;除了第一个之外的其他的GPU默认是不参与计算的。为了让Tensor…

java和网易我的世界有什么区别_网易我的世界手机版对比正版JAVA版我的世界有什么区别?...

你说的这部分都属于游戏内部机制问题首先网易手机版实质上就是基岩版&#xff0c;还是更新贼慢的基岩版(笑)。所以题主完全可以去minecraft wiki查找相关资料然后我说一下我知道的一些主要差异吧刷怪效率吧基岩版明显不如java版&#xff0c;所以通用的黑暗刷怪塔在基岩版是不怎…

python jieba词频统计英文文本_python实战,中文自然语言处理,应用jieba库来统计文本词频...

模块介绍安装&#xff1a;pip install jieba 即可jieba库&#xff0c;主要用于中文文本内容的分词&#xff0c;它有3种分词方法&#xff1a;1. 精确模式, 试图将句子最精确地切开&#xff0c;适合文本分析&#xff1a;2. 全模式&#xff0c;把句子中所有的可以成词的词语都扫描…

java修改已创建程序界面_Java应用程序的Web用户界面

应用服务器。您认为Tomcat在运行时占用空间、学习量或…?我倾向于选择与一个IDE有良好集成的东西。所以EclipseTomcat或者ApacheGeronimo,可能在里面WebSphere Community Edition伪装可以完成这项工作。从我所看到的情况来看,这些足以满足您的需求,而且学习曲线实际上是可以管…

python+selenium获取cookie session_selenium获取cookie及设置cookie

获取cookie&#xff1a;在打开的页面使用self.driver.get_cookies()返回下面数据&#xff1a;[{domain: .linkedin.com,expiry: 1553,httpOnly: False,name: liap,path: /,secure: False,value: true},{domain: .linkedin.com,expiry: 154613,httpOnly: False,name: lidc,path:…

js url解码gbk_JS中对URL进行转码与解码

1. escape 和 unescapeescape()不能直接用于URL编码&#xff0c;它的真正作用是返回一个字符的Unicode编码值。采用unicode字符集对指定的字符串除0-255以外进行编码。所有的空格符、标点符号、特殊字符以及更多有联系非ASCII字符都将被转化成%xx格式的字符编码(xx等于该字符在…

python常用模块用法_python常用模块(一)

#什么是模块呢&#xff1f;就是用一大坨代码来完成一个功能的代码集合&#xff0c;是不是简单易懂#类似于函数式编程和面向过程编程&#xff0c;函数式编程则完成一个功能&#xff0c;其他代码用来调用即可&#xff0c;提供了代码的重用性和代码间的耦合。而对于一个复杂的功能…