首页 > 数据库 >MySQL优化

MySQL优化

时间:2024-06-30 19:52:44浏览次数:1  
标签:name 查询 select MySQL 排序 优化 id SELECT

MySQL优化

1、尽量避免使用子查询

例:

SELECT * FROM t1 WHERE id (SELECT id FROM t2 WHERE name = 'chackca');

其子查询在Mysql5.5版本里,内部执行计划是这样:先查外表再匹配内表,而不是先查内表t2,当外表的数据很大时,查询速度会非常慢

在MariaDB10/Mysql5.6版本里,采用join关联方式对其进行了优化,这条SQL语句会自动转换为:

SELECT t1.* FROM t1 JOIN t2 on t1.id = t2.id

但请注意的是:优化只针对SELECT有效,对UPDATE/DELETE子查询无效,固生产环境应避免使用子查询

由于MySQL的优化器对于子查询的处理能力比较弱,所以不建议使用子查询,可以改写成Inner Join,之所以 join 连接效率更高,是因为 MySQL不需要在内存中创建临时表

2、用IN来替换OR

  • 低效查询
SELECT * FROM t WHERE id = 10 OR id = 20 OR id = 30;
  • 高效查询
SELECT * FROM t WHERE id IN (10,20,30);

另外,MySQL对于IN做了相应的优化,即将IN中的常量全部存储在一个数组里面,而且这个数组是排好序的。但是如果数值较多,产生的消耗也是比较大的。再例如:

select id from table_name where num in(1,2,3)

对于连续的数值,能用 between 就不要用 in 了;再或者使用连接来替换。

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

select id,name from t limit 866613, 20

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

对于 limit m, n 的分页查询,越往后面翻页(即m越大的情况下)SQL的耗时会越来越长,对于这种应该先取出主键id,然后通过主键id跟原表进行Join关联查询。因为MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后放弃前 offset 行,返回 N 行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行 SQL 改写

优化的方法如下:可以取前一页的最大行数的id(将上次遍历到的最末尾的数据ID传给数据库,然后直接定位到该ID处,再往后面遍历数据),然后根据这个最大的id来限制下一页的起点。比如此列中,上一页最大的id是866612。sql可以采用如下的写法:

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

4、禁止不必要的Order By排序

如果我们对结果没有排序的要求,就尽量少用排序;

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

另外,分组统计查询时可以禁止其默认排序

SELECT goods_id,count(*) FROM t GROUP BY goods_id;

默认情况下,Mysql会对所有的GROUP BT col1,col2…的字段进行排序,也就是说上述会对 goods_id进行排序,如果想要避免排序结果的消耗,可以指定ORDER BY NULL禁止排序:

SELECT goods_id,count(*) FROM t GROUP BY goods_id ORDER BY NULL

5、总和查询可以禁止排重用union all

union和union all的差异主要是前者需要将结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的CPU运算,加大资源消耗及延迟

当然,union all的前提条件是两个结果集没有重复数据。所以一般是我们明确知道不会出现重复数据的时候才建议使用 union all 提高速度

6、避免随机取记录

SELECT * FROM t1 WHERE 1 = 1 ORDER BY RAND() LIMIT 4;        SELECT * FROM t1 WHERE id >= CEIL(RAND()*1000) LIMIT 4;

以上两个语句都无法用到索引

7、将多次插入换成批量Insert插入

INSERT INTO t(id, name) VALUES(1, 'aaa');        INSERT INTO t(id, name) VALUES(2, 'bbb');        INSERT INTO t(id, name) VALUES(3, 'ccc');        —>        INSERT INTO t(id, name) VALUES(1, 'aaa'),(2, 'bbb'),(3, 'ccc');

8、只返回必要的列,用具体的字段列表代替 select * 语句

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

MySQL数据库是按照行的方式存储,而数据存取操作都是以一个页大小进行IO操作的,每个IO单元中存储了多行,每行都是存储了该行的所有字段。所以无论取一个字段还是多个字段,实际上数据库在表中需要访问的数据量其实是一样的。

但是如果查询的字段都在索引中,也就是覆盖索引,那么可以直接从索引中获取对应的内容直接返回,不需要进行回表,减少IO操作。除此之外,当存在 order by 操作的时候,select 子句中的字段多少会在很大程度上影响到我们的排序效率。

9、区分in和exists

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

上面的语句相当于:

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

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

另外,in查询在某些情况下有可能会查询返回错误的结果,因此,通常是建议在确定且有限的集合时,可以使用in。如 IN (0,1,2)

10、优化Group By语句

如果对group by语句的结果没有排序要求,要在语句后面加 order by null(group 默认会排序);

尽量让group by过程用上表的索引,确认方法是explain结果里没有Using temporary 和 Using filesort;

如果group by需要统计的数据量不大,尽量只使用内存临时表;也可以通过适当调大tmp_table_size参数,来避免用到磁盘临时表;

  • 如果数据量实在太大,使用SQL_BIG_RESULT这个提示,来告诉优化器直接使用排序算法(直接用磁盘临时表)得到group by的结果

使用where子句替换Having子句:避免使用having子句,having只会在检索出所有记录之后才会对结果集进行过滤,这个处理需要排序分组,如果能通过where子句提前过滤查询的数目,就可以减少这方面的开销

  • 低效
SELECT JOB, AVG(SAL) FROM EMP GROUP by JOB HAVING JOB = ‘PRESIDENT’ OR JOB = ‘MANAGER’
  • 高效
SELECT JOB, AVG(SAL) FROM EMP WHERE JOB = ‘PRESIDENT’ OR JOB = ‘MANAGER’ GROUP by JOB

11、尽量使用数字型字段

若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能。引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了

12、优化Join语句

当我们执行两个表的Join的时候,就会有一个比较的过程,逐条比较两个表的语句是比较慢的,因此可以把两个表中数据依次读进一个内存块中,在Mysql中执行:

show variables like ‘join_buffer_size’

可以看到join在内存中的缓存池大小,其大小将会影响join语句的性能。在执行join的时候,数据库会选择一个表把他要返回以及需要进行和其他表进行比较的数据放进join_buffer

标签:name,查询,select,MySQL,排序,优化,id,SELECT
From: https://www.cnblogs.com/zhangyf1121/p/18276861

相关文章

  • 深入解析MySQL语句的执行步骤
    目录MySQL架构概述语句执行步骤总览连接管理与线程处理语法解析查询缓存语义解析与预处理查询优化执行计划生成存储引擎层执行结果集返回优化查询性能的技巧结论MySQL架构概述在深入探讨MySQL语句执行的具体步骤之前,我们先来了解MySQL的整体架构。MySQL架构主要包括以下......
  • 基于JSP和MySQL的小说阅读网站系统
    开头语:你好,我是计算机专业的猫哥,如果你对小说阅读网站感兴趣,欢迎联系我。开发语言:JSP数据库:MySQL技术:JSP+Java工具:MySql数据库,Java开发工具系统展示首页管理员功能模块读者后台功能模块作者后台功能模块摘要随着网络的发展,小说阅读行业迅速壮大,小说阅读网......
  • Fastapi 项目第二天首次访问时数据库连接报错问题Can't connect to MySQL server
    问题描述Fastapi项目使用sqlalchemy连接的mysql数据库,每次第二天首次访问数据库相关操作,都会报错:sqlalchemy.exc.OperationalError:(pymysql.err.OperationalError)(2003,"Can'tconnecttoMySQLserveron'x.x.x.x'([Errno111]Connectionrefused)")问题分析从出......
  • MySQL 常见性能问题排除
     随着时间的推移,即使是设计良好的数据库也会遇到性能问题,这些问题源于各种因素,如数据的增长、次优的索引策略、优化不佳的查询或不均衡的服务器配置。 常见的性能问题1.查询速度慢最常见的性能问题之一是查询执行缓慢。缓慢的查询会增加等待时间,阻碍应用程序的响应速度,从......
  • 解读MySQL 8.0数据字典的初始化与启动
    本文分享自华为云社区《MySQL全文索引源码剖析之Insert语句执行过程》,作者:GaussDB数据库。本文主要介绍MySQL8.0数据字典的基本概念和数据字典的初始化与启动加载的主要流程。MySQL8.0数据字典简介数据字典(DataDictionary,DD)用来存储数据库内部对象的信息,这些信息也被称......
  • 【SQL】MySQL 的基础架构
    MySQL是一种广泛使用的开源关系型数据库管理系统,其架构设计具有高度的可扩展性和灵活性。理解MySQL的基础架构有助于更好地配置、优化和管理MySQL数据库。下面是MySQL的基础架构概述:MySQL架构概览MySQL的架构主要分为以下几个层次:连接层(ConnectionLayer)服务层(S......
  • 详解 ClickHouse 的查询优化
    一、单表查询1.使用prewhere替代whereprewhere和where语句的作用相同,都是用来过滤数据prewhere和where语句的不同在于:prewhere只支持MergeTree族系列引擎的表prewhere首先会读取指定的列数据来判断数据过滤,等待数据过滤之后再读取select声明的列字段......
  • 【MySQL】掌握 ALTER TABLE 的艺术:灵活修改表结构的全方位指南
    【MySQL】掌握ALTERTABLE的艺术:灵活修改表结构的全方位指南一、引言:MySQL数据库的基石与本文使命二、技术概述:`ALTERTABLE`的威力初探定义与核心特性核心优势代码示例:增加新列三、技术细节:深入`ALTERTABLE`的背后原理剖析特性与难点四、实战应用:场景与解决方案应......
  • MySQL数据库管理
    一:使用MySQL数据库1:查看数据库结构[root@localhost~]#mysql-uroot-ppwd123mysql>showdatabases;mysql>usemysqlmysql>showtables;mysql>describeuser;mysql>select*fromuser\G;备注:information_schema数据库:保存着关于MySQL服务器所维护的所......
  • MySQL数据库管理
    一、使用MySQL数据库1.1查看数据库结构1.查看当前服务器中的数据库2.查看当前数据库中有哪些表3.查看表的结构        数据库目前标准的指令集是SQL。SQL是StructuredQueryLanguage的缩写,即结构化查询语言。它是1974年由Boyce和Chamberlin提出来......