关于数据库优化你知道多少?(代码片段)

流楚丶格念 流楚丶格念     2022-10-22     545

关键词:

文章目录

什么是数据库优化?

MySQL数据库优化是多方面的,原则是减少系统的瓶颈,减少资源的占用,增加系统的反应速度。

针对于数据库,我们可以通过使用下面方法进行优化:

  • 通过优化文件系统,提高磁盘I\\O的读写速度;
  • 通过优化操作系统调度策略,提高MySQL在高负荷情况下的负载能力;
  • 优化表结构、索引、查询语句等使查询响应更快;

针对于查询语句,我们可以通过优化查询操作:

  • 针对查询,我们可以通过使用索引、使用连接代替子查询的方式来提高查询速度。
  • 针对慢查询,我们可以通过分析慢查询日志,来发现引起慢查询的原因,从而有针对性的进行优化。
  • 针对插入,我们可以通过禁用索引、禁用检查等方式来提高插入速度,在插入之后再启用索引和检查。
  • 针对数据库结构,我们可以通过将字段很多的表拆分成多张表、增加中间表、增加冗余字段等方式进行优化。

好多啊,下面我们来看看里面的细节:

优化MySQL的查询

使用索引:

如果查询时没有使用索引,查询语句将扫描表中的所有记录。在数据量大的情况下,这样查询的速度会很慢。如果使用索引进行查询,查询语句可以根据索引快速定位到待查询记录,从而减少查询的记录数,达到提高查询速度的目的。

索引可以提高查询的速度,但并不是使用带有索引的字段查询时索引都会起作用。有几种特殊情况,在这些情况下有可能使用带有索引的字段查询时索引并没有起作用。

  1. 使用LIKE关键字的查询语句

    在使用LIKE关键字进行查询的查询语句中,如果匹配字符串的第一个字符为“%”,索引不会起作用。只有“%”不在第一个位置,索引才会起作用。(最左前缀原则)

  2. 使用多列索引的查询语句

    MySQL可以为多个字段创建索引。一个索引可以包括16个字段。对于多列索引,只有查询条件中使用了这些字段中的第1个字段时索引才会被使用。(最左前缀原则)

  3. 使用OR关键字的查询语句

    查询语句的查询条件中只有OR关键字,且OR前后的两个条件中的列都是索引时,查询中才使用索引。否则,查询将不使用索引。

    注意:并不是有OR不能使用索引。

优化子查询:

使用子查询可以进行SELECT语句的嵌套查询,即一个SELECT查询的结果作为另一个SELECT语句的条件。子查询可以一次性完成很多逻辑上需要多个步骤才能完成的SQL操作。

子查询虽然可以使查询语句很灵活,但执行效率不高。执行子查询时,MySQL需要为内层查询语句的查询结果建立一个临时表。然后外层查询语句从临时表中查询记录。查询完毕后,再撤销这些临时表。因此,子查询的速度会受到一定的影响。如果查询的数据量比较大,这种影响就会随之增大。

在MySQL中,可以使用连接(JOIN)查询来替代子查询。连接查询不需要建立临时表,其速度比子查询要快,如果查询中使用索引,性能会更好

优化MySQL的插入

影响插入速度的主要是索引、唯一性校验、一次插入记录条数等。针对这些情况,可以分别进行优化。

MyISAM引擎

对于MyISAM引擎的表,常见的优化方法如下:

  1. 禁用索引

    对于非空表,插入记录时,MySQL会根据表的索引对插入的记录建立索引。如果插入大量数据,建立索引会降低插入记录的速度。为了解决这种情况,可以在插入记录之前禁用索引,数据插入完毕后再开启索引。对于空表批量导入数据,则不需要进行此操作,因为MyISAM引擎的表是在导入数据之后才建立索引的。

  2. 禁用唯一性检查

    插入数据时,MySQL会对插入的记录进行唯一性校验。这种唯一性校验也会降低插入记录的速度。为了降低这种情况对查询速度的影响,可以在插入记录之前禁用唯一性检查,等到记录插入完毕后再开启。

  3. 使用批量插入

    插入多条记录时,可以使用一条INSERT语句插入一条记录,也可以使用一条INSERT语句插入多条记录。使用一条INSERT语句插入多条记录的情形如下,而这种方式的插入速度更快。

    INSERT INTO fruits VALUES 
    ('x1', '101', '啦啦啦', '5.7'), 
    ('x2', '101', '咕咕咕', '5.7'), 
    ('x3', '101', '呼呼呼', '5.7');
    
  4. 使用LOAD DATA INFILE批量导入

    当需要批量导入数据时,如果能用LOAD DATA INFILE语句,就尽量使用。因为LOAD DATA INFILE语句导入数据的速度比INSERT语句快。

InnoDB引擎

对于InnoDB引擎的表,常见的优化方法如下:

  1. 禁用唯一性检查

    插入数据之前执行 set unique_checks=0 来禁止对唯一索引的检查,数据导入完成之后再运行 set unique_checks=1 。这个和MyISAM引擎的使用方法一样。

  2. 禁用外键检查

    插入数据之前执行禁止对外键的检查,数据插入完成之后再恢复对外键的检查。

  3. 禁用事务自动提交

    插入数据之前禁止事务的自动提交,数据导入完成之后,执行恢复自动提交操作。

海量数据处理优化

表中包含几千万条数据该怎么办?

建议按照如下顺序进行优化:

  1. 优化SQL和索引;
  2. 增加缓存,如memcached、redis;
  3. 读写分离,可以采用主从复制,也可以采用主主复制;
  4. 使用MySQL自带的分区表,这对应用是透明的,无需改代码,但SQL语句是要针对分区表做优化的;
  5. 做垂直拆分,即根据模块的耦合度,将一个大的系统分为多个小的系统;
  6. 做水平拆分,要选择一个合理的sharding key,为了有好的查询效率,表结构也要改动,做一定的冗余,应用也要改,sql中尽量带sharding key,将数据定位到限定的表上去查,而不是扫描全部的表。

MySQL的慢查询优化

慢查询概念

慢查询,顾名思义,执行很慢的查询。有多慢?超过 long_query_time 参数设定的时间阈值(默认10s),就被认为是慢的,是需要优化的。慢查询被记录在慢查询日志里。

然而,慢查询日志默认是不开启的,也就是说一般人没玩过这功能。如果你需要优化SQL语句,就可以开启这个功能,它可以让你很容易地知道哪些语句是需要优化的(想想一个SQL要10s就可怕)。

优化MySQL的慢查询,可以按照如下步骤进行:

开启慢查询日志:

MySQL中慢查询日志默认是关闭的,可以通过配置文件my.ini或者my.cnf中的log-slow-queries选项打开,也可以在MySQL服务启动的时候使用 --log-slow-queries[=file_name] 启动慢查询日志。

启动慢查询日志时,需要在my.ini或者my.cnf文件中配置long_query_time选项指定记录阈值,如果某条查询语句的查询时间超过了这个值,这个查询过程将被记录到慢查询日志文件中。

分析慢查询日志:

直接分析mysql慢查询日志,利用explain关键字可以模拟优化器执行SQL查询语句,来分析sql慢查询语句。

1. 索引没起作用的情况

在使用LIKE关键字进行查询的查询语句中,如果匹配字符串的第一个字符为“%”,索引不会起作用。只有“%”不在第一个位置,索引才会起作用(最左前缀原则)。

MySQL可以为多个字段创建索引。一个索引可以包括16个字段。对于多列索引,只有查询条件中使用了这些字段中的第1个字段时索引才会被使用(最左前缀原则)。

查询语句的查询条件中只有OR关键字,且OR前后的两个条件中的列都是索引时,查询中才使用索引。否则,查询将不使用索引。

2. 优化数据库结构

对于字段比较多的表,如果有些字段的使用频率很低,可以将这些字段分离出来形成新表。

因为当一个表的数据量很大时,会由于使用频率低的字段的存在而变慢。

对于需要经常联合查询的表,可以建立中间表以提高查询效率。通过建立中间表,把需要经常联合查询的数据插入到中间表中,然后将原来的联合查询改为对中间表的查询,以此来提高查询效率。

3. 分解关联查询

很多高性能的应用都会对关联查询进行分解,就是可以对每一个表进行一次单表查询,然后将查询结果在应用程序中进行关联,很多场景下这样会更高效。

4. 优化LIMIT分页

当偏移量非常大的时候,例如可能是limit 10000,20这样的查询,这是mysql需要查询10020条然后只返回最后20条,前面的10000条记录都将被舍弃,这样的代价很高。

优化此类查询的一个最简单的方法是尽可能的使用索引覆盖扫描,而不是查询所有的列。然后根据需要做一次关联操作再返回所需的列。对于偏移量很大的时候这样做的效率会得到很大提升。

关于springboot自动装配你知道多少?(代码片段)

文章目录什么是springboot自动装配?SpringBoot自动装配的过程自动装配源码分析@ComponentScan@EnableAutoConfiguration小总结细节问题为什么不使用@Import直接引入自动配置类什么是springboot自动装配?自动装配是springboot的核... 查看详情

输入与输出函数——关于python输入和输出你知道多少?(代码片段)

输入与输出函数——关于python输入和输出你知道多少?文章目录输入与输出函数——关于python输入和输出你知道多少?1️⃣输入print()🍹基本语法🍹%格式化🍹format()格式化🍹f-strings格式化2️⃣输入input()&... 查看详情

关于混淆,你需要知道的全部(代码片段)

 proguard流程 proguard分为4个步骤:压缩(shrink)移除未使用的类、方法、字段等;优化(optimize)优化字节码、简化代码等操作;混淆(obfuscate)使用简短的、无意义的名称重全名类名、方法名... 查看详情

关于线程上下文切换,你知道多少?(代码片段)

点击关注公众号,实用技术文章及时了解由于现在大多计算机都是多核CPU,多线程往往会比单线程更快,更能够提高并发,但提高并发并不意味着启动更多的线程来执行。更多的线程意味着线程创建销毁开销加大... 查看详情

mysql数据库的优化,你知道有哪些?(代码片段)

...注“终端研发部”设为“星标”,和你一起掌握更多数据库知识来源| sf.gg/a/1190000018631870数据库优化一方面是找出系统的瓶颈,提高MySQL数据库的整体性能,而另一方面需要合理的结构设计和参数调整,以提高用户的相应速度,同... 查看详情

mysql数据库的优化,你知道有哪些?(代码片段)

...注“终端研发部”设为“星标”,和你一起掌握更多数据库知识来源| sf.gg/a/1190000018631870数据库优化一方面是找出系统的瓶颈,提高MySQL数据库的整体性能,而另一方面需要合理的结构设计和参数调整,以提高用户的相应速度,同... 查看详情

关于混淆,你需要知道的全部(代码片段)

 proguard流程 proguard分为4个步骤:压缩(shrink)移除未使用的类、方法、字段等;优化(optimize)优化字节码、简化代码等操作;混淆(obfuscate)使用简短的、无意义的名称重全名类名、方法名... 查看详情

你知道如何优化join语句吗?(代码片段)

join语句的两种算法,分别是:NLJ和BNL测试数据:createtablet1(idintprimarykey,aint,bint,index(a));createtablet2liket1;dropprocedureidata;delimiter;;createprocedureidata()begindeclareiint;seti=1;while(i<=1000)doinserti 查看详情

关于meta你知道多少

META标签,是HTML语言head区的一个辅助性标签。在几乎所有的page里,我们都可以看到类似下面这段html代码:-----------------------------------------------<head><metahttp-equiv="Content-Type"content="text/html;charset=gb2312"></head& 查看详情

关于android性能监控matrix那些事?你知道那些(中)?(代码片段)

昨天更新了关于Android性能监控Matrix那些事?你知道那些(上)?说的的视频也更新了:微信Matrix卡顿监控实战,函数自动埋点监控方案今天我们接着聊下文:4.Hprof文件分析5.卡顿监控6.卡顿监控源码解析7.插... 查看详情

ios底层探索之多线程(十四)—关于@synchronized锁你了解多少?(代码片段)

对于多线程你了解多少?对于锁你又了解多少?锁的原理你又知道吗?iOS底层探索之多线程(一)—进程和线程iOS底层探索之多线程(二)—线程和锁iOS底层探索之多线程(三)—初识GCDiOS底层探索之多线程(四)—GCD的队列iOS... 查看详情

arcgis微课1000例0020:关于arccatalog,你知道多少?

...口7.工具栏二、ArcCatalog主要功能1.文件夹连接2.添加空间数据库连接3.文件类型的添加和移除4.文件特性的显示设置5.导出数据6.查看数据7.ArcCatalog中图层的操作一、ArcCatalog简介 查看详情

关于数据标注行业有些你不知道的事儿(代码片段)

一位在觉醒向量做数据标注的员工说:正如别人评论的那样,我们的工作的确很像数字世界的建筑工人,但是我们在扮演着很重要的角色,因为没有我们,AI这栋摩天大楼就无法建成。大数据作为一个术语而言,其历史可能并不... 查看详情

关于数据库时区,这么多奥秘你都知道么?(代码片段)

...的过程。GaussDB(DWS)作为一款面向全球用户的高性能分析型数据库产品,对时区的支持也是符合工业界 查看详情

js的console你知道多少(代码片段)

js的console你知道多少?列出所有的console属性console.dir(console)或者console.dirxml(console)记录代码执行时间console.time("test");varcount=0;for(vari=0;i<10000;i++)count++;console.timeEnd("test");输出消息格式化console.log("Hello 查看详情

java反射-修改privatefinal成员变量值,你知道多少?(代码片段)

大家都知道使用java反射可以在运行时动态改变对象的行为,甚至是privatefinal的成员变量,但并不是所有情况下,都可以修改成员变量。今天就举几个小例子说明。 基本数据类型String类型Integer类型总结首先看下对基本类型的... 查看详情

可能你不知道的,关于自动装箱和自动拆箱(代码片段)

包装类我们知道,Java中包含了8种基本数据类型:整数类型:byte、short、int、long字符类型:char浮点类型:float、double布尔类型:boolean这8种基本数据类型的变量不需要使用new来创建,它们不会在堆上创建,而是直接在栈内存中存... 查看详情

关于hashmap你需要知道的一些细节(代码片段)

本文的公众号文章链接:关于HashMap你需要知道的一些细节在官方文档中的描述:HashtablebasedimplementationoftheMapinterface.Thisimplementationprovidesalloftheoptionalmapoperations,andpermitsnullvaluesandthenullkey.(TheHashMa 查看详情