热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入浅出MySQL:SQL优化常用的SQL优化

一、大批量插入数据MyISAM表的插入优化,插入前先关闭索引更新。altertablexxxDISABLEKEYS;--关闭索引更新--插入数据altertablexxxEN

一、大批量插入数据

MyISAM 表的插入优化,插入前先关闭索引更新。


alter table xxx DISABLE KEYS; -- 关闭索引更新
... -- 插入数据
alter table xxx ENABLE KEYS;

InnoDB 表的插入优化:

1)导入的数据按主键排列,效率更高。因为 Innodb 数据是按主键顺序排列的

2)关闭唯一性校验


SET UNIQUE_CHECKS = 0;
-- 插入数据
SET UNIQUE_CHECKS = 1;

3)如果应用使用自动提交(事务)的方式,则插入前关闭自动提交,有助于提高效率


SET AUTOCOMMIT = 0;
-- 插入数据
SET AUTOCOMMIT = 1;

二、优化 insert 语句

1)数据量较大时,采用批量插入代替多条insert语句


insert into xx values(1, 2), (3, 4), (5, 6) ...;

2)如果从不同客户端插入多行时,使用 insert delayed 提高速度。该语句让 insert 马上执行,数据放入内存的队列中,并没有真正写入磁盘,比每条语句插入更快。

3)将索引与数据文件分在不同磁盘存放(通过建表的选项)

4)对于MyISAM,增加 bulk_insert_buffer_size 值提高批量插入速度

5)Load data infile 比多条 insert 快近 20 倍。

三、优化 order by 语句

1)MySQL 两种排序方式

a. 有序索引顺序扫描直接返回有序数据


select customer_id from customer order by store_id; -- Using index 效率高

b. 对返回结果进行排序


select * from customer order by store_id; -- Using Filesort

通过explain查看Extra是否为Using index,Using index效率高于Using Filesort

Filesort 将取得的数据在 sort_buffer_size 系统变量设置的内存排序区进行排序,若内存装不下,将磁盘的数据分块,再对各个数据块进行排序,然后各个块合并成有序结果集。 sort_buffer_size 设置的排序区是每个线程独占的,在同一时刻,MySQL 存在多个 sort buffer 排序区

优化目标:尽量减少额外排序,通过索引直接返回有效数据。

下列 order by 语句将使用索引:


select * from xxx order by key_part1, key_part2 ...; -- 同属于一个联合索引
select * from xxx where key_part1 = xxx order by key_part1 desc, key_part2 desc, ...;

下列 order by 语句将不使用索引:


select * from xxx order by key_part1 desc, key_part2 asc; -- 混合desc与asc
select * from xxx where key_part2 = xxx order by key_part1; -- where与order by的字段不一致
select * from xxx order by key1, key2; -- key1与key2属于两个不同的关键字

2)filesort 优化

对于 filesort 存在两种排序算法

两次扫描算法:第一次获取排序字段和行指针信息,第二次根据行指针获取记录(产生大量随机I/O),该算法内存开销较小。

一次扫描算法:一次取出所有满足条件的行,在排序区进行排序后直接输出结果。内存开销大,效率高。

a)适当加大 max_length_for_sort_data 使其使用更优化的排序算法(一次扫描)

b)适当加大 sort_buffer_size 尽量让排序在内存中完成,而不是通过创建临时表放在文件中进行。

c)select 具体字段 代替 select * ,可减少排序区的使用

四、优化 group by 语句

默认情况下,MySQL会对group by的所有字段进行排序,可禁止该排序:


select xxx from xxx group by xxx order by null;

五、优化嵌套查询


select * from customer where customer_id not in (select customer_id from payment);
select * from customer a left join payment b on a.customer_id = b.customer_id where b.customer_id is null;
-- join代替子查询效率更好,因为join不需要在内存中创建临时表。

六、优化Or条件

对OR的每个字段增加索引,否则执行时涉及的索引将都不使用

七、优化分页查询

limit 1000,20 :MySQL 会对所有进行排序,但仅需要返回20条,明显查询的代价很高

1)优化思路一:在索引上完成排序分页,然后通过主键再从元表查找其他所需要的字段


select film_id, description from film order by title limit 50,5; -- Using Filesort
select a.film_id, a.description from film a inner join (select film_id from film order by title limit 50,5) b on a.film_id = b.film_id;
-- Using index
因为--
select film_id from film order by title limit 50,5 会使用索引
select film_id, description from film order by title limit 50,5; 不会使用索引

2)将Limit n,m 转为 Limit m (适用于排序字段不会出现重复值)


select * from xxx order by abc limit 400, 10;
select * from xxx where id

八、使用SQL提示


select count(*) from xxx use index (xxx); -- 建议MySQL使用索引XXX
select count(*) from xxx ignore index (xxx); -- 让MySQL忽略使用索引XXX
select count(*) from xxx force index (xxx); -- 强制让MySQL使用索引XXX,尽管效率很低

 



推荐阅读
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • mysql-cluster集群sql节点高可用keepalived的故障处理过程
    本文描述了mysql-cluster集群sql节点高可用keepalived的故障处理过程,包括故障发生时间、故障描述、故障分析等内容。根据keepalived的日志分析,发现bogus VRRP packet received on eth0 !!!等错误信息,进而导致vip地址失效,使得mysql-cluster的api无法访问。针对这个问题,本文提供了相应的解决方案。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了如何在MySQL中将零值替换为先前的非零值的方法,包括使用内联查询和更新查询。同时还提供了选择正确值的方法。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 本文详细介绍了MysqlDump和mysqldump进行全库备份的相关知识,包括备份命令的使用方法、my.cnf配置文件的设置、binlog日志的位置指定、增量恢复的方式以及适用于innodb引擎和myisam引擎的备份方法。对于需要进行数据库备份的用户来说,本文提供了一些有价值的参考内容。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • Python SQLAlchemy库的使用方法详解
    本文详细介绍了Python中使用SQLAlchemy库的方法。首先对SQLAlchemy进行了简介,包括其定义、适用的数据库类型等。然后讨论了SQLAlchemy提供的两种主要使用模式,即SQL表达式语言和ORM。针对不同的需求,给出了选择哪种模式的建议。最后,介绍了连接数据库的方法,包括创建SQLAlchemy引擎和执行SQL语句的接口。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
author-avatar
阳光-假日
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有