SQL语句优化

news/2024/10/6 3:33:18/文章来源:https://www.cnblogs.com/hjqx/p/18287132

SQL语句优化

  • 插入数据优化

    • 批量插入

      注:通过测试,若插入一千万条数据,不使用批量插入,每条一个insert需要耗费时间10分钟左右,但若是通过批量插入耗费时间为十几秒左右 ,由此可见使用批量插入可以极大的提高性能,同时减少多次访问数据库对数据库造成的压力。

      注:若在springboot或springcloud中使用批量插入,需要在写连接到数据库的配置时将批量插入的开关打开,否则即使你在使用 insert in() 时也不会使用批量插入。

      如果一次性需要插入大量数据,使用insert语句插入性能较低,此时可以使用MySQL数据库提供的load命令进行插入。

      前提:本地需要插入数据的文件中文件的内容需要符合规范。每个字段使用逗号分隔。(这里的逗号可以是别的符号,但必须保持一致)

      在数据库管理工具中使用批量插入的语句:

      #客户端连接服务端时,加上参数 --local-infile
      mysql --local-infile -u root -p
      #设置全局参数local——infile为1,开启从本地加载文件导入数据的开关
      set global local_infile = 1;
      #执行load指令将准备好的数据,加载到表结构中
      load data local infile '/rooot/sql1.log' (文件名) into table 'tb_user'(表名) fileds terminated by ','(设置字段间分割符) lines terminated by '\n';(设置换行符号)
      
    • 手动提交事务

    若不手动控制事务,每条sql语句都会是一个单独的事务,降低性能,而开启手动后可以多条sql语句一起提交,优化性能。

    • 主键顺序插入(与b+tree结构有关,涉及到页分裂)
  • 主键优化

    • 数据组织方式

      在InnoDB引擎中,表数据都是根据主键顺序组织存放的,这种存储方式的表称为索组织表。(想想B+Tree底层叶子结点结构,

      之前的文章里有,也可去百度B+Tree结构模型)

      所以建议主键存储时使用自增,在符合要求的情况下,尽量降低主键的长度,且使用自增,不要使用UUID随机生成,尽量避免产生页分裂。

  • order by 优化

    1. Using filesort:通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区sort buffer中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫做FileSort排序。该方法进行排序性能相对较低。

    2. Using index:通过有序索引顺序扫描直接返回有序数据,这种情况即为using index,不需要额外排序,操作效率高。

      所以我们在进行优化时尽量使进行排序时使用Using index

      例:

      #没有创建索引时
      select id,age,phone from tb_user order by age,phone (Using filesort)
      #创建索引
      create index idx_user_age_phone_aa on tb_user(age,phone)
      #创建索引后,根据age,phone进行升序排序
      select id,age,phone from tb_user order by age,phone (Using index)
      #创建索引后,根据age,phone进行降序排序
      select id,age,phone from tb_user order by age desc,phone desc (Using index)
      #根据age,phone进行排序,一个使用升序,一个使用降序
      select id,age,phone from tb_user order by age asc,phone desc; (Using filesort)
      #创建索引
      create index idx_user_age_phone_ad on tb_user(age asc,phone desc); (创建索引时age根据升序创建,phone根据降序创建)
      #根据age,phone进行排序,一个降序,一个升序
      select id,age,phone from tb_user order by age asc,phone desc; (Using index)
      
      • 根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则。(前面的文章有介绍最左前缀法则)
      • 尽量使用覆盖索引。
      • 多字段排序,一个升序一个降序,此时需要注意联合索引在创建时的规则(ASC/DESC)
      • 如果不可避免的出现filesort,大量数据排序时,可以适当增加排序缓冲区大小sort_buffer_size(默认256k)。
  • group by 优化

    #执行分组 操作,根据profession字段进行排序
    select profession,count(*) from tb_user group by profession (Using temporary 使用临时表,性能低)
    #创建索引
    create index idx_user_pro_age_sta on tb_user(profession,age,status);
    #执行分组操作,根据profession字段分组
    select profession,count(*) from tb_user group by profession (Using index)
    #执行分组操作,根据age字段分组
    select age,count(*) from tb_user group by age (Using temporary 不满足最左前缀法则)
    #执行分组操作,根据profession进行筛选,age字段排序
    select age,count(*) from tb_user where profession = ‘软件工程’ group by age;(Using index 满足最左前缀法则)
    • 在分组操作时,可以通过索引来提高效率。
    • 分组操作时,索引的使用也是满足最左前缀法则的。
  • limit 优化

    • 一个常见又非常头疼的问题就是 limit 2000000,10,此时需要MySQL排序前2000010记录,仅仅返回2000000-2000010的记录,其他记录丢弃,查询排序的代价非常大。

    • 通过覆盖索引加子查询的方式优化:

      例:

      select * from tb_sku t,(select id from tb_sku order by id limit 2000000,10) a where t.id = a.id
      #此条sql语句如果看不懂可以先了解下多表查询中的子查询和自连接查询
      
  • count 优化

    • MyISAM引擎把一个表的总行数存在了磁盘上,因此执行count(*)的时候会直接返回这个数,效率很高;

    • InnoDB引擎就很麻烦了,他执行count(*)的时候,需需要把数据一行一行的从引擎里面读出来,然后累积计数。

    • 优化思路:自己计数

    • count的几种用法:

      • count是一个聚合函数,对于返回的结果集,一行行地判断,如果count函数的参数不是NULL,累计值就加一,否则不加,最后返回累计值

      • 用法:count(*)、count(主键)、count(字段)、count(1)

      • count(主键): InnoDB引擎会遍历整张表,把每一行的主键id取出来,返回给服务层。服务层拿到主键后,直接按行进行累加(主键不可能为null)。

      • count(字段):

        • 没有NOT null约束:InnoDB引擎会遍历整张表把每一行的字段都取出来,返回给服务层,服务层判断是否为null,不为null,计数累加。
        • 有NOT null 约束:InnoDB引擎会遍历整张表把每一行的字段值都取出来,返回给服务层,直接进行累加。
      • count(1):InnoDB引擎遍历整张表,但不取值。服务层对于返回的每一行,放一个数字1进去,直接按行进行累加。

      • count(*):InnoDB引擎并不会把全部字段取出来,而是专门做了优化,不取值,服务层直接按行进行累加。

        所以性能:count(字段)<count(主键)<count(1)≈count(*)

  • update 优化

    update student set no='20000100' where id = 1 #id为主键,必然有索引,所以加的是行锁
    
    update student set no='199999987' where name = '韦一笑' #(若是name没有设置索引,那么在修改时会加表锁,降低性能)
    

    InnoDB的行锁是针对索引加的锁,不是针对记录加的锁,并且该索引不能失效,否则会从行锁升级为表锁

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

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

相关文章

【模块三】Python高级

面向对象基础 类和对象 概念 面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式。 类是人们抽象出来的一个概念,所有拥有相同属性和功能的事物称为一个类;而拥有相同属性和功能的具体事物则成为这个类的实例对象。 面向对象编程提供了一种从现实世界中抽象…

大气热力学(5)——绝热过程

本篇文章源自我在 2021 年暑假自学大气物理相关知识时手写的笔记,现转化为电子版本以作存档。相较于手写笔记,电子版的部分内容有补充和修改。笔记内容大部分为公式的推导过程。 目录5.1 气块的概念5.2 热力学第一定律的几种微分形式5.3 干绝热过程5.4 干绝热递减率(干绝热直…

如何解决服务器开机报警问题

解决服务器开机报警问题,需要按照一系列步骤进行故障排查和修复。 一、初步检查与确认 查看报警信息: 观察服务器的指示灯,特别是电源指示灯、硬盘指示灯等,看是否有异常。 如果服务器有显示屏或终端窗口,查看是否有相应的警告信息或错误代码。 确认电源状态: 检查电源线…

用友财务软件数据库恢复

是一个关键的操作,旨在解决数据库文件损坏或数据丢失的问题。 一、恢复方法使用软件内置的数据恢复工具 步骤: 打开用友财务软件,进入“工具”或“数据管理”等相关菜单。 找到“数据库恢复”或“数据恢复”选项,点击进入。 选择需要恢复的数据库文件和备份文件。这里需要确…

管家婆数据库数据恢复

一、确认数据丢失情况 首先,需要确认数据是否真的丢失,以及丢失的数据范围。有时候,数据可能只是暂时无法访问,或者由于软件故障导致的数据显示问题。 二、检查备份定期备份的重要性 管家婆软件通常会具备自动备份功能,用户应该确保该功能已经开启,并定期检查备份文件的完…

服务器进水主板维修

服务器进水主板的维修是一个复杂且需要专业技能的过程。 一、立即断电与初步处理 立即断电:一旦发现服务器进水,应立即切断电源,防止电流通过水分造成短路,进一步损坏主板和其他电子元件。 移除电池与外设:如果是笔记本电脑或可拆卸电池的服务器,迅速移除电池和所有外部连…

sqlserver数据库MDF文件修复

针对SQL Server数据库的MDF文件修复,这是一个相对复杂的过程,具体方法取决于文件的损坏程度、是否有备份以及数据库的状态。以下是一些常见的修复方法:使用备份恢复 这是最直接且最可靠的方法。如果你有数据库的备份,并且备份是在MDF文件损坏之前创建的,那么你可以通过还原…

2024年6月后2周重要的大语言模型论文总结:LLM进展、微调、推理和对齐

本文总结了2024年6月后两周发表的一些最重要的大语言模型论文。这些论文涵盖了塑造下一代语言模型的各种主题,从模型优化和缩放到推理、基准测试和增强性能。 LLM进展与基准 1、 BigCodeBench: Benchmarking Code Generation with Diverse Function Calls and Complex Instruc…

龙城新闻

2024-07-02 5月30日龙岗重点新闻2024-07-02 51月30日龙岗重点新闻打开app立即下载10月1日龙城重点新闻龙城街道宣传部 2024-10-1 龙城街道宣传部 2024年10月1日 全区要闻 ●“高质量发展龙岗行”系列报道 | 近日,龙岗区举办高层建筑无人机消防应用示范项目签约仪式,率先…

基于CFX的小型风电机组流场计算流程

一、WOrkbench界面框架二、Geometry模块操作 1.打开Geometry模块,导入txt格式模型File >> Import External Geometry File2.绘制圆柱体作为风轮旋转域3.绘制长方体作为流场计算域4.根据模型与计算条件,做了旋转,根据实际情况选择和操作5.布尔运算第1步:计算域 — (旋…

基于CFX的小型风电机组流程计算流程

一、WOrkbench界面框架二、Geometry模块操作 1.打开Geometry模块,导入txt格式模型File >> Import External Geometry File2.绘制圆柱体作为风轮旋转域3.绘制长方体作为流场计算域4.根据模型与计算条件,做了旋转,根据实际情况选择和操作5.布尔运算第1步:计算域 — (旋…

初始C++

1.visual studio2022 创建项目以及创建C++文件完成上述步骤之后我们就可以敲代码了!!2.关于编译和链接 1.ctrl+F7 对当前C++文件进行编译 并会在编译成功后生成.obj文件。 2.F5 运行整个项目 就会将一个项目下的所有 C++文件进行编译 再将编译后生成的.obj文件链接起来生成 一…