SQL优化怎么做?大量数据实战分析

如果你对sql优化不了解,请认真看完这篇文章,并跟着文章动手操作一下,这篇文章讲解了所有方面的优化技巧

一:基础数据准备

二:五百万数据插入

上面插入几条测试数据,在使用索引时还需要插入更多的数据作为测试数据,下面就通过存储过程插入500W条数据作为测试数据

三:使用索引和不使用索引的比较

没有添加索引前一个简单的查询用了1.79秒

创建索引,然后再查询可以看到耗时0.00秒,这就是索引的威力

四:explain命令

explain命令用于查看sql执行时是否使用了索引,是优化SQL语句的一个非常常用而且非常重要的一个命令, 上面中的key字段表示查询使用到的索引即使用了idx_username索引

id: SELECT识别符。这是SELECT的查询序列号

select_type: 查询类型

simple: 简单表即不适用表连接或者子查询

primary: 主查询,即外层的查询

subquery: 子查询内层第一个SELECT,结果不依赖于外部查询

dependent subquery: 子查询内层第一个

select: 依赖于外部查询

union: UNION语句中第二个SELECT开始后面所有SELECT

union result union 中合并结果

DERIVED

table:查询的表

partitions

type:扫描的方式,all表示全表扫描

all : 全表扫描

index: 扫描所有索引

range: 索引范围扫描,常见于< <=、>、>=、between、

const: 表最多有一个匹配行, 常见于根据主键或唯一索引进行查询

system: 表仅有一行(=系统表)。这是const联接类型的一个特例

ref

possible_keys: 该查询可以利用的索引,可能同一个查询有多个索引可以使用,如果没有任何索引显示null

key: 实际使用到的索引,从Possible_key中所选择使用索引,当有多个索引时,mysql会挑出一个最优的索引来使用

key_len: 被选中使用索引的索引长度

ref:

多表连接时的外键字段

const

rows: 估算出结果集行数,该sql语句扫描了多少行,可能得到的结果,MySQL认为它执行查询时必须检查的行数

filtered:

Extra:额外重要的信息

no tables: Query语句中使用FROM DUAL 或不含任何FROM子句

using filesort : 使用文件排序,最好能避免这种情况

Using temporary: 某些操作必须使用临时表,常见 GROUP BY ; ORDER BY

Using where: 不用读取表中所有信息,仅通过索引就可以获取所需数据;

Using join buffer (Block Nested Loop)

Using index condition

Using sort_union(索引名)

查看索引的使用情况:

show status like ‘Handler_read%’;

Handler_read_key: 越高越好

Handler_read_rnd_next:越低越好

查询优化器:

重新定义表的关联顺序(优化器会根据统计信息来决定表的关联顺序)

将外连接转化成内连接(当外连接等于内连接)

使用等价变换规则(如去掉1=1)

优化count()、min()、max()

子查询优化

提前终止查询

in条件优化

mysql可以通过 EXPLAIN EXTENDED 和 SHOW WARNINGS 来查看mysql优化器改写后的sql语句

五:走索引的情况和不走索引的情况

1. in走索引

in操作能避免则避免,若实在避免不了,需要仔细评估in后边的集合元素数量,控制在1000个之内。

2. 范围查询走索引

3. 模糊查询只有左前缀使用索引

4. 反向条件不走索引 != 、 <> 、 NOT IN、IS NOT NULL

5. 对条件计算(使用函数或者算数表达式)不走索引

使用函数计算不走索引,无论是对字段使用了函数还是值使用了函数都不走索引,解决办法通过应用程序计算好,将计算的结果传递给sql,而不是让数据库去计算

id是主键,id/10使用了算数表达式不走索引

6. 查询时必须使用正确的数据类型

如果索引字段是字符串类型,那么查询条件的值必须使用引号,否则不走索引

7. or 使用索引和不使用索引的情况

or 只有两边都有索引才走索引,如果都没有或者只有一个是不走索引的

8. 用union少用or

尽量避免使用or,因为大部分or连接的两个条件同时都进行索引的情况几率比较小,应使用uninon代替,这样能走索引的走索引,不能走索引的就全表扫描。

9. 能用union all就不用union

union all 不去重复,union去重复,union使用了临时表,应尽量避免使用临时表

10. 复合索引

对于复合索引,如果单独使用右边的索引字段作为条件时不走索引的。即复合索引如果不满足最左原则leftmost不会走复合索引

11. 覆盖索引

覆盖索引是select的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖。

当能通过读取索引就可以得到想要的数据,那就不需要读取行了。一个索引包含了(或覆盖了)满足查询结果的数据就叫做覆盖索引。

它包括在查询里的Select、Join和Where子句用到的所有列(即建索引的字段正好是覆盖查询条件中所涉及的字段,也即,索引包含了查询正在查找的数据)

覆盖索引:根据关键字就能够直接获取查询所需要的所有数据,不必要读取数据行的数据,所有数据是指where、select从句、order by、 group by从句的值

如果索引字段是字符串那么查询条件必须加引号,但是如果查询的列都在索引中,即使不满足走索引的条件,此时也会使用索引。示例中order_code=666666,是数字类型,没有加引号,按说是不走索引的,但是select * 而test表只有两个字段,id和order_code而这两个字段都创建了索引,这种情况也会走索引

12. order by

mysql有两种排序方式:

通过有序索引顺序扫描直接返回有序数据,通过explain分析显示Using Index,不需要额外的排序,操作效率比较高。

通过对返回数据进行排序,也就是Filesort排序,所有不是通过索引直接返回排序结果的都叫Filesort排序。Filesort是通过相应的排序算法将取得的数据在sort_buffer_size系统变量设置的内存排序中进行排序,如果内存装载不下,就会将磁盘上的数据进行分块,再对各个数据块进行排序,然后将各个块合并成有序的结果集

order by 使用索引的严格要求:

索引的顺序和order by子句的顺序完全一致

索引中所有列的方向(升续、降续)和order by 子句完全一致

当多表连接查询时order by中的字段必须在关联表中的第一张表中

如果有 order by 的场景,请注意利用索引的有序性。order by 最后的字段是组合 索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能。

正例:where a=? and b=? order by c; 索引:a_b_c

反例:索引中有范围查找,那么索引有序性无法利用,如:WHERE a>10 ORDER BY b; 索引 a_b 无法排序

order by如果根据多个值进行排序,那么排序方式必须保持一致,要么同时升续,要么同时降续,排序方式不一致不走索引

13. group by

默认情况下,group by column;有两个作用,第一个就是根据指定的列进行分组,第二作用group by 不但分组,而且还为分组中的数据按照列来排序,如果分组的字段创建了索引,那么排序也没什么毕竟排序走索引也很快

但是如果group by指定的列没有走索引,而我们通常情况下只对分组中的数据进行统计,例如对分组中的数据求和,通常顺序无关紧要,此时就要关闭group by 的排序功能,使用Order By NULL;来关闭排序功能,避免排序对性能的影响。

14. 分页limit

分页查询一般会全表扫描,优化的目的应尽可能减少扫描;

第一种思路:在索引上完成排序分页的操作,最后根据主键关联回原表查询原来所需要的其他列。这种思路是使用覆盖索引尽快定位出需要的记录的id,覆盖索引效率高些

第二中思路:limit m,n 转换为 n

之前分页查询是传pageNo页码, pageSize分页数量,

当前页的最后一行对应的id即last_row_id,以及pageSize,这样先根据条件过滤掉last_row_id之前的数据,然后再去n挑记录,此种方式只能用于排序字段不重复唯一的列,如果用于重复的列,那么分页数据将不准确

当只一行数据使用limit 1

多表连接查询连接条件(也就是外键必须创建索引,否则大数据查询直接卡死)

如果全表扫描比使用索引快,就不会使用索引,比如 表的数量很少或者满足条件的数据量比较大也不走索引, 查询数据库记录时,查询到的条目数尽量小,当通过索引获取到的数据库记录> 数据库总记录的1/3时,SQL将有可能直接全表扫描,索引就失去了应有的作用。

where条件将能过滤掉多的条件写在前面,过滤掉少部分的数据写在后面,这样先排除一大部分不满足条件的数据,然后剩下一小部分数据,然后再从中找出满足条件的记录

数据类型不匹配是不会走索引,例如对字符串类型创建索引,where条件值却没有使用引号,就不走索引,join语句中join条件字段类型不一致的时候MYSQL无法使用索引

15 in和exists

查询所有下过订单的用户(tbl_user 500w条数据,tbl_order 3条数据), 有两种方式,一种使用in另一种使用exists,但是两者效率相差很大

in的伪代码:

SELECT * FROM A WHERE id IN (SELECT a_id FROM B) 当A表中的数据量远大于B表中的数据量时使用in

查询用户id大于10的用户的订单信息

从以上逻辑可以看到exists每次循环一下外表都要查询一下内表,即使外表数量很少,但是每循环一次外表都要去查询一个大表,这样的效率是不高的,除非子查询走索引,最好走覆盖索引。

SELECT * FROM B o WHERE exists(SELECT 1 FROM A WHERE o.user_id > 10) 网上说当B表的数据量小A表的数据量很大时用exists。上面那个例子没有测试出来,实际优化时in和exists具体那个好根据具体执行情况来选择,也不能一味的就说某种情况下用这个就比那个快

16. 强制索引

当查询时不走索引时可以通过force index 强制mysql使用指定的索引,一般情况下如果mysql不走索引它是认为全表扫描会更快些,可以通过强制走索引看一下查询时间,如果强制索引效果更好,查询速度更快就使用强制索引,如果强制索引没有明显效果就没必要使用了。

mysql强制使用索引:force index(索引名或者主键PRI)

-- 强制使用主键索引

select * from table force index(PRI);

-- 强制使用索引"idx_xxx"

select * from table force index(idx_xxx);

-- 强制使用索引"PRI"和"idx_xxx"

select * from table force index(PRI,idx_xxx);

mysql禁止某个索引:ignore index(索引名或者主键PRI)

-- 禁止使用主键

select * from table ignore index(PRI)

-- 禁止使用索引"idx_xxx"

select * from table ignore index(idx_xxx);

-- 禁止使用索引"PRI","idx_xxx"

select * from table ignore index(PRI,idx_xxx);

六:其它优化

1、禁止使用select *,需要什么字段就去取哪些字段

2、超过三个表禁止join。需要join的字段数据类型必须绝对一致;多表关联查询时,保证被关联的字段需要有索引。说明:即使双表 join 也要注意表索引、SQL 性能。尽可能避免复杂的join和子查询。尽量使用左右连接,少使用内连接。永远小结果集驱动大结果集(这点mysql会自动优化)

3、不要使用count(列名)或 count(常量)来替代 count(),count()是SQL92定义的标准统计行数的语法,跟数据库无关,跟 NULL和非NULL无关。说明:count(*)会统计值为NULL 的行,而count(列名)不会统计此列为NULL值的行。

4、不得使用外键与级联,一切外键概念必须在应用层解决。

5、禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。避免使用存储过程、触发器。

6、使用表连接来优化子查询。尽量避免使用子查询,建议将子查询转换成关联查询,子查询的效率并没有连接join查询快(并不绝对),连接查询之所以更有效率一些,是因为mysql不需要再内存中创建临时表来完成这个逻辑上需要两个步骤的查询工作。对于多表连接,如果连接条件创建索引效率更高。

7、对于列类型是字符串,值必须使用单引号括住,如果没有引号引住就不走索引, 结论:字符串必须使用‘’引住

8、拒绝大SQL,拆分成小SQL

9、优先优化高并发的SQL,而不是执行频率低某些“大”SQL

10、在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。

11、减少 IO 次数

IO永远是数据库最容易瓶颈的地方,这是由数据库的职责所决定的,大部分数据库操作中超过90%的时间都是 IO 操作所占用的,减少 IO 次数是 SQL 优化中需要第一优先考虑,当然,也是收效最明显的优化手段。

12、降低 CPU 计算

除了 IO 瓶颈之外,SQL优化中需要考虑的就是 CPU 运算量的优化了。order by, group by,distinct … 都是消耗 CPU 的大户(这些操作基本上都是 CPU 处理内存中的数据比较运算)。当我们的 IO 优化做到一定阶段之后,降低 CPU 计算也就成为了我们 SQL 优化的重要目标

13、大表的数据修改最好要分批处理,例如1000万行的记录删除更新 100万行记录,可以一次只删除更新5000行记录,暂停几秒,然后再执行剩下的数据。

如何修改大表的表结构:

先在从服务器上修改,然后将从服务器改为主服务器,然后再从主服务器上修改,然后再切换回来,此种方式需要切换主从,有一定的风险。

在主服务器上创建一张新表,将老表的数据迁移到新表,创建一个触发器,将老表的新数据同步到新表中,对老表加一个排它锁,重新命名新表和老表,然后删除掉老表(整个操作过程比较复杂,可以通过工具来实现)

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

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

相关文章

一次简单的postgreSQL的SQL语句优化实际案例

文章目录 业务背景初版查询SQL这段SQL有什么问题呢执行计划实际执行 初次优化执行计划2实际执行 继续优化再次优化的SQL执行计划3实际执行 疑问 业务背景 我上篇文章介绍了一个规则引擎的简单使用&#xff0c;主要就是为了众包业务批量录入数据的一些校验的统一管理&#xff0…

PostgreSQL之如何进行SQL优化?

文章目录 一、明确主题二、目标三、如何进行SQL优化&#xff1f;3.1 pg_stat_activity系统内置活动视图视图主要字段wait_event_typestate 3.2 pg_stat_statement SQL执行统计视图3.2.1 pg_stat_statements 视图详细说明中文版(简版) 3.2.2 常见案例 Top SQL 3.3 大表的索引使用…

以防作弊,ChatGPT 遭教育部「拉黑」:师生禁用!

来源&#xff1a;FUTURE远见 选编&#xff1a;FUTURE | 远见 闵青云 CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 文 上个月&#xff0c;弗曼大学哲学助理教授 Darren Hick 逮到一个用 ChatGPT 写论文的作弊者后&#xff0c;就感慨&#xff1a;「ChatGPT 太先进了&am…

ChatGPT国产化:ChatYuan元语对话大模型升级

国产自研功能对话大模型元语 ChatYuan 于 2022 年 12 月发布测试版本后&#xff0c;引起社会各界人士的广泛讨论&#xff0c;并且收到了用户的大量反馈和宝贵建议。元语智能团队已于近日对元语 ChatYuan 进行了模型效果优化和版本功能升级&#xff0c;现已开放内测。 &#xff…

体验联网版 ChatGPT:优点和缺点同样明显,还藏着无限可能

ChatGPT 有点像古希腊的阿喀琉斯&#xff1a;它很强大&#xff0c;却有个致命的弱点——无法联网&#xff0c;这注定了它只能是一个停留在 2021 年的超人。 但很快&#xff0c;我们将等到一个「鱼和熊掌兼得」的时刻。 通过插件集的 Web browsing 功能&#xff0c;ChatGPT 就…

教你写接口需求文档

作者&#xff1a;果果 转载已取得作者授权 一、什么是接口 百科上对接口的定义&#xff1a;API&#xff08;Application Programming Interface,应用程序编程接口&#xff09;是一些预先定义的函数&#xff0c;目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的…

什么是反向代理,开放的反向代理软件使用方法

什么是反向代理呢&#xff1f;其实&#xff0c;反向代理也就是通常所说的WEB服务器加速&#xff0c;它是一种通过在繁忙的WEB服务器和Internet之间增加一个高速的WEB缓冲服务器&#xff08;即&#xff1a;WEB反向代理服务器&#xff09;来降低实际的WEB服务器的负载。 Web服务器…

反向正向代理

https://www.zhihu.com/question/36412304

宝塔反代教程

近期有网友问宝塔如何设置反向代理&#xff0c;小编这里介绍一种简单的操作方法&#xff0c;就是使用宝塔官方软件面板自带的反向代理功能来实现。首先您要先安装宝塔面板&#xff0c;当Nginx或LNMP环境配置完成后&#xff0c;便可开始设置反向代理了&#xff0c;下面来看下操作…

[转发]图示说明正向代理和反向代理

关于代理 说到代理&#xff0c;首先我们要明确一个概念&#xff0c;所谓代理就是一个代表、一个渠道&#xff1b; 此时就设计到两个角色&#xff0c;一个是被代理角色&#xff0c;一个是目标角色&#xff0c;被代理角色通过这个代理访问目标角色完成一些任务的过程称为代理操…

Linux宝塔面板反向代理设置教程

此方法最简单快捷&#xff0c;没有复杂步骤&#xff0c;不容易出错&#xff0c;即最简单&#xff0c;零代码、零部署的方法。 实现准备 一台服务器安装宝塔面板OpenAI官方的API_KEYChatGPT网站系统源码 ChatGPT网站系统源码&#xff0c;大家可以看看另一篇文章介绍&#xff…

网关V.S反向代理

简介 网关主要服务于微服务/API&#xff0c;偏向研发人员反向代理主要面向传统静态web应用&#xff0c;偏向运维而未来趋势是DevOps网关和反向代理再次融合 发展趋势 WEB1.0/2.0时代&#xff0c;使用前置反向代理&#xff0c;由运维负责 nginx&#xff0c;进行反向代理和负载…

反向代理

先看这张图 反向代理&#xff08;Reverse Proxy&#xff09;方式是指以代理服务器来接受internet上的连接请求&#xff0c;然后将请求转发给内部网络上的服务器&#xff0c;并将从服务器上得到的结果返回给internet上请求连接的客户端&#xff0c;此时代理服务器对外就表现为一…

图解正向代理和反向代理

套用古龙武侠小说套路来说&#xff0c;代理服务技术是一门很古老的技术&#xff0c;是在互联网早期出现就使用的技术。一般实现代理技术的方式就是在服务器上安装代理服务软件&#xff0c;让其成为一个代理服务器&#xff0c;从而实现代理技术。常用的代理技术分为正向代理、反…

代理,正向代理和反向代理

1. 代理 代理也被叫做网络代理&#xff0c;是一种比较特殊的网络服务&#xff0c;允许一个终端&#xff08;通常指客户端&#xff09;通过这个服务与另一个终端&#xff08;通常指服务器端&#xff09;进行非直接的连接。 例如&#xff1a;一些网关、路由器等网络设备都具备网…

反向代理,正向代理,网关

反向代理&#xff0c;正向代理&#xff0c;网关 正向代理与反向代理&#xff0c;正向与反向是如何区分的&#xff1f;反向代理在系统架构中的应用场景&#xff1a; 正向代理与反向代理&#xff0c;正向与反向是如何区分的&#xff1f; 正向与反向的目标是客户端&#xff0c;是…

2、正向代理和反向代理(正向代理(客户端),反向代理(服务器))

正向代理和反向代理&#xff08;正向代理&#xff08;客户端&#xff09;&#xff0c;反向代理&#xff08;服务器&#xff09;&#xff09; 1、正向代理&#xff1a;&#xff08;代理客户端&#xff09; 说个例子&#xff08;访问外网&#xff09;&#xff1a;我们的客户端先…

正向代理 / 反向代理

1. 正向代理 正向代理是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须设置正向代理服务器,当然前提是要知道正…

chatgpt赋能python:Python中的JWT解码(Decode)

Python中的JWT解码&#xff08;Decode&#xff09; 什么是JWT&#xff08;JSON Web Token&#xff09;&#xff1f; JSON Web Token&#xff08;JWT&#xff09;是目前最流行的 Web 身份验证方案之一。JWT 是基于 JSON 的开放标准&#xff0c;它可以让客户端和服务器之间传递…

对接支付宝php版easysdk接口分享

在网上没有找到支付宝easysdk接口的对接详细说明&#xff0c;自己一步一步的摸索&#xff0c;其中使用chatgpt的帮助作用不少。 根据官方给的文档 需要执行composer require alipaysdk/easysdk:^2.0安装sdk。如果你的项目已经安装过其它扩展&#xff0c;可以先把vendor文件夹备…