SQL查询优化

article/2025/10/23 0:16:47

                                           SQL查询优化

一、获取有性能问题SQL的三种方法

  1.     通过用户反馈获取存在性能问题的SQL
  2.     通过慢查询日志获取存在性能问题的SQL
  3.     实时获取存在性能问题的SQL

二、慢查询日志介绍

    1、使用慢查询日志获取有性能问题的SQL

        (1) 参数配置

            slow_query_log 启动停止记录慢查询日志

                . 启动:ON;

                . 如果在已经运行的Mysql中启动慢查询日志功能,可以直接使用set global命令;

                . 为了避免慢查询日志占用太多的存储空间,如果需要在指定的某一时间段内开启慢查询日志功能,可以通过脚本来定时的开关。

            slow_query_log_file 指定慢查询日志的存储路径及文件

                . 默认情况下保存在MYSQL的数据目录中

                . 日志存储和数据存储分开存储

            long_query_time 指定记录慢查询日志SQL执行时间的伐值        

                . 默认值为10秒

                . 通常改为0.001秒也就是1毫秒可能比较合适

                . 记录范围:记录所有符合条件的SQL;包括查询语句;数据修改语句;已经回滚的SQL

            log_queries_not_using_indexes 是否记录未使用索引的SQL

        (2) 慢查询日志中记录的内容

            

            第一行:记录运行这条SQL的用户信息和用户线程ID号

            第二行:记录了执行这条SQL所使用的时间(精确到毫秒)

            第三行:记录了执行这条SQL所使用的锁的时间(精确到毫秒)

            第四行:记录了执行这条SQL返回的数据的行数

            第五行:记录了执行这条SQL扫描的数据的行数

            第六行:记录了执行这条SQL所用的时间(时间戳的形式)

            第七行:记录了我们所执行的SQL

        (3) 常用的慢查询日志分析工具(mysqldumpslow

            汇总除查询条件外其他完全相同的SQL,并将分析结果按照参数中所指定的顺序输出。

            mysqldumpslow -s r -t 10 slow-mysql.log

            -s order(c, t, l, r, at, al, ar)

                指定按那种排序方式输出结果

            

            -t top

                指定取前几条作为结束输出

        (4) 常用的慢查询日志分析工具(pt-query-digest

            安装过程自行百度

            pt-query-digest --explain h=127.0.0.1,u=root,p=p@ssWord iZwz948fbj8fd62q3tskypZ-slow.log

三、慢查询日志实例

    

    

    

    

    

    

四、实时获取性能问题

    可以通过mysql的information_schema数据库下的PROCESSLIST表实时的发现具有性能问题的SQL

    

    set global long_query_time=0;

    set global slow_query_log=on;

    select id, user, host, db, command, time, state, info from information_schema.processlist;

    select id, user, host, db, command, time, state, info from information_schema.processlist\G;    

    

    

五、SQL的解析预处理及生成执行计划

    1、查询速度为什么会慢

        (1) MySQL服务器处理查询请求的整个过程

            . 客户端发送SQL请求给服务器

            . 服务器检查是否可以在查询缓存中命中该SQL

            . 服务器端进行SQL解析,预处理,再由优化器生成对应的执行计划

            . 根据执行计划,调用存储引擎API来查询数据

            . 将结果返回给客户端

            在解析一个查询语句之前,如果查询缓存是打开的,那么MySQL会优先检查这个查询查询是否命中查询缓存中的数据。这个检查是通过一个对大小写敏感的哈希查找实现的。

            Hash查找只能进行全值匹配,所以请求的查询和缓存中的查询,即使只有一个字节的不同,那么也不会匹配到缓存中的结果。

            如果当前的查询恰好命中了查询缓存,那么在返回结果之前,MySQL就会检查用户权限,这任然是无需解析查询SQL语句的,因为查询缓存中已经存在了当前查询需要访问的一些表的信息,如果权限没有问题,MySQL会跳过所有的其他阶段,直接从缓存中拿到结果,并返回给客户端。这种情况下,查询是不会被解析的,也不会生成查询计划,不会被执行。

    2、查询缓存对SQL性能的影响

        从查询缓存中直接返回结果并不容易。

        每次在缓存中检查SQL是否命中时,都要对缓存加锁,所以对于一个读写频繁的系统使用查询缓存很可能会降低查询处理的效率。所以在这种情况下建议大家不要使用查询缓存。

        (1) 对查询缓存存在影响的一些系统参数

            query_cache_type 设置查询缓存是否可用

                ON, OFF, DEMAND

                DEMAND表示只有在查询语句中使用SQL_CACHE和SQL_NO_CACHE来控制是否需要缓存。

            query_cache_size 设置查询缓存的内存大小

                单元字节必须是1024的整数倍。

            query_cache_limit 设置查询缓存可用存储的最大值

                超过这个值就不会被缓存了,如果预先我们知道结果很大,不会被缓存,那么我们在查询上加上SQL_NO_CACHE可以提高效率。

            query_cache_wlock_invalidate 设置数据表被锁后是否返回缓存中的数据

                默认关闭。

            query_cache_min_res_unit 设置查询缓存分配的内存块最小单位

        (2) MySQL依照这个执行计划和存储引擎进行交互

            这个阶段包括了多个子过程:

                解析SQL,预处理,优化SQL执行计划。

                . 语法解析阶段是通过关键字对MySQL语句进行解析,并生成一棵对应的“解析树”;

                    MySQL解析器将使用MySQL语法规则验证和解析查询

                        检查语法是否使用了正确的关键字

                        关键字的顺序是否正确

                . 预处理阶段是根据MySQL规则进一步检查解析树是否合法;

                    检查查询中所涉及的表和数据列是否存在及名字或别名是否存在歧义等等

                语法检查全都通过了,查询优化器就可以生成查询计划了。

        (3) 会造成MySQL生成错误的执行计划的原因

            . 统计信息不准确

                存储引擎提供的信息。

            . 执行计划中的成本估算不等同于实际的执行计划的成本

                MySQL服务器层并不知道哪些页面在内存中;哪些页面在磁盘上;哪些需要顺序读取;哪些页面要随机读取

            . MySQL优化器所认为的最优可能与你所认为的最优不一样

            . MySQL从不考虑其他并发的查询,这可能会影响当前查询的速度

            . MySQL有时候也会基于一些固定的规则来生成执行计划

            . MySQL不会考虑不受其控制的成本

                存储过程、用户自定义的函数

        (4) MySQL优化器可优化的SQL类型

            . 重新定义表的关联顺序

            . 将外连接转化成内连接

                where条件和库表结构等都可以使外连接等价于内连接。

            . 使用等价变换规则

                (5=5 and a > 5)将被改写为a > 5

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

                select tables optimized away

                优化器已经从执行计划中移除了该表,并以一个常熟取而代之

            . 将一个表达式转化为常数表达式

            . 子查询优化

                子查询转换为关联查询,可以减少查询的次数

            . 提前终止查询

                表中dilm_id字段为无符号整型,当其值为-1时,就会终止查询。

                

            . 对in()条件进行优化

                MySQL将in列表中的数据先进行排序,然后通过二分查找的方式来确定列表中的值是否满足条件。

六、如何确定查询处理各个阶段所消耗的时间

    1、使用profile

        set profiling = 1;

        启动profile

            这是一个session级的配置,只有在当前session下,才能起作用。启动profile后,在服务器上执行的所有语句都会记录其消耗的时间和其他一些查询执行的状态。

        执行查询

        show profiles;

            查看每一个查询所消耗的总时间的信息。

        show profile for query N;

            查询每个阶段所消耗的时间。

        实例:

            set profiling = 1;

            

            select count(*) from film;

            

             show profiles;

            

            show profile for query 1;

            

            show profile cpu for query 1;

            

    2、使用performance_schema

        设置语句:

            UPDATE 'setup_instruments' SET enabled='YES', TIMED='YES' WHERE NAME LIKE 'stage%';

            UPDATE setup_consumers SET enabled='YES' WHERE NAME LIKE 'events%';

        执行语句:

select a.thread_id, sql_text, c.event_name, (c.timer_end - c.timer_start)/1000000000 as 'duration(ms)' 
from events_statements_history_long a 
join threads b on a.thread_id=b.thread_id 
join events_stages_history_long c on c.thread_id=b.thread_id and c.event_id between a.event_id and a.end_event_id 
where b.processlist_id=connection_id() and a.event_name='statement/sql/select' 
order by a.thread_id, c.event_id

        执行结果:

        

七、特定SQL的查询优化

    1、大表的数据修改最好要分批处理

        1000万行记录的表中删除/更新100万行记录一次只删除/更新5000行记录

        为了减少主从复制同步带来的压力,我们可以在每次修改数据后暂停几秒,给主从复制集群提供一个同步数据的时间。

    2、大表的删除        

 delimiter$$use 'imooc'$$drop procedure if exists 'p_delete_rows'$$create definer='root'@'127.0.0.1' procedure 'p_delete_rows'()begindeclare v_rows int;set v_rows = 1; while v_rows > 0 do delete from 'sbtest1' where id >= 9000 and id <= 19000 limit 5000;select row_count() into v_rows;select sleep(5); end while;
end$$
delimiter;  

    3、如何修改大表的表结构

        对表中的列的字段类型进行修改

        改变字段的宽度时还是会锁表

        无法解决主从数据库延迟的问题

        (1) 方案一:

            利用主从复制服务器架构,先在从服务器上进行修改,

            

            然后进行主从切换,

            

            最后在老的主服务器上进行修改。

            

        (2) 方案二:

            在主服务器上建立一个新的表,这个新表的结构就是要修改之后的这个表的结构;

            然后再把老表的数据导入到新表中;

            并且在老表上建立一系列的触发器,把老表数据的修改也同步更新到新表中;

            当老表和新表数据同步后,对老表加一个排它锁,重新命名新表和老表的名字;

            最后删除重命名后的老表。

            

            由于实现过程复杂,我们可以借助工具:

                alter:对语句进行的修改

                user:执行这个修改的执行用户的用户名,用户对需要修改表结构的表要有修改其表结构的权限

                password:执行这个修改的执行用户的密码

                D:要修改的表所在的数据库名

                t:要修改的表的表名

                charset:指定表的字符集          

                execute:指定是否执行这个修改

                pt-online-schema-change --alter="MODIFY c VARCHAR(150) NOT NULL DEFAULT ''" --user=root --password=PassWord D=imooc,t=sbtest4 --charset=utf8 --execute

                

                

                

    4、如何优化not in和<>查询

        SELECT customer_id, first_name, last_name, email

        FROM customer

        WHERE customer_id

        NOT IN (SELECT customer_id FROM payment)

 

        SELECT customer_id, first_name, last_name, email

        FROM customer a

        LEFT JOIN payment b ON a.customer_id=b.customer_id

        WHERE b.customer_id IS NULL

    5、使用汇总表优化查询

        SELECT COUNT(*) FROM product_comment WHERE product_id = 999

        汇总表就是提前以要统计的数据进行汇总并记录到表中以备后续的查询使用。

        如上SQL查询可进行如下优化:

            新创建一个表,统计出截止前一天每一个商品评论数数据的汇总

            CREATE TABLE product_comment_cnt(product_id INT, cnt INT);

            显示每个商品的评论数:

                SELECT SUM(cnt) FROM (

                 SELECT cnt FROM product_comment_cnt WHERE product_id=999

                 UNION ALL

                 SELECT COUNT(*) FROM product_comment WHERE product_id=999 AND timestr>DATE(NOW())

                ) a

友情提示:

    博主每天写博客也很辛苦,如果您觉得这篇博客对您有帮助,就赏博主一块两块的,给博主买个包子吃,以便能写出更好的博客,谢谢。

    如果内容中有不对的地方,或是有更好的方案,也欢迎大家提出来,共同学习!


http://chatgpt.dhexx.cn/article/S81OPFYd.shtml

相关文章

sql查询排序

查询排序 如果需要针对查询后的结果&#xff0c;按照指定的数据列进行排序操作&#xff0c;就必须使用ORDER BY 默认排序&#xff1a;按照数据的插入顺序。 select * from emp;观察 语法格式 【3控制要显示的数据列】SELECT[DISTINCT]*|列名称[别名]&#xff0c;列名称[别名…

SQL 查询数据

数据库表是存储数据库中所有数据的对象。 在表中&#xff0c;数据按行和列格式逻辑组织&#xff0c;类似于电子表格 (Excel) 在表中&#xff0c;每行代表一个唯一记录&#xff0c;每列代表记录中的一个字段。 例如&#xff0c; SC表包含学生成绩数据&#xff0c;如学生标识号&a…

SQL之查询

因为同一SQL语句&#xff0c;不同厂商有不同的实现方式&#xff0c;因此同一SQL语句不一定在所有的数据库编辑器上能够正确运行&#xff0c;这里采用的是华为的openGauss。 基本格式为&#xff1a; SELECT desired attributes FROM one or more tables WHERE condition about…

SQL查询与操作

1.单表查询 SQL 数据查询主要由 SELECT 语句完成&#xff0c;SELECT 语句是SQL 的核心。单表查询就是利用 SELECT语句仅从一个表/视图中查询数据。其语法如下: SELECT [DISTINCT]*{ 字段名 1&#xff0c;字段名 2&#xff0c; 字段名 3,… FROM 表名 [WHERE 条件表达式 1] [GR…

sql的查询

sql的查询 &#xff08;1&#xff09;什么是排序 order by&#xff08;2&#xff09;如何排序 》》数据库的查询(排序:order by) SELECT * FROM 表名 ORDER BY 排序字段 ASC(升序)|DESC(降序);&#xff08;3&#xff09;特点 指定列 指定升序或者降序 order by 排序只对数字和…

SQL 数据查询

前言&#xff0c;数据库中有5个表&#xff0c;student&#xff0c;sc,course,tc,teacher;(sql server里面不区分大小写) student sc tc course teacher 1. 查询软件工程学院&#xff08;SE&#xff09;学生的学…

SQL数据查询

目录 1、求各系学生的平均成绩&#xff0c;并把结果存入新建的数据库表中&#xff08;请自己创建一个表存放结果&#xff09; 2、统计每门课程的选修学生人数及各门课程的平均成绩 3、找出各系年龄最大的学生&#xff0c;显示其学号、姓名&#xff1b;&#xff08;利用相关子…

数据库:SQL数据查询(详细、全面)

以下题目中加粗字体为重点哦~ 一、查询指定列、全部列 1.查询全体学生的学号和姓名 SELECT SNO, SN FROM S 2.查询全部列 SELECT * FROM S 二、查询经过计算的值 3. 查询全体学生的姓名、出生年份 SELECT SN, 2020-AGE FROM S 4. 查村全体学生的姓名、出生年份和系名&#xff…

2022留学生落户上海成本大概是怎样的?

现在留学生落户上海整体来说除了对于社保没有要求的落户方式&#xff0c;那么对于普通的留学生落户来说&#xff0c;就得有社保和个税的要求了&#xff0c;那么这里面的成本是有多少呢&#xff0c;下面来看看这里面的情况&#xff1a; 留学生落户上海根据判断自己的社保基数及累…

非上海户籍人员在上海买房需要啥条件?

和你一起终身学习&#xff0c;这里是程序员Android 非沪籍想在上海买房说实话有点难&#xff0c;毕竟每平米大几万的房价不是盖的&#xff0c;既然您点进来看了&#xff0c;说明你有这个想法&#xff0c;有想法就行&#xff0c;虽然我们不一定能买得起&#xff0c;但不能阻挡我…

上海落户计算机水平毕业研究生,2021上海积分落户应届毕业生直接落户上海

原标题&#xff1a;2021上海积分落户应届毕业生直接落户上海 ——上海落户积分120分&#xff0c;不是研究生毕业就有100分吗&#xff1f;研究生毕业就有100分&#xff0c;正常读书年龄肯定很小就有30分了啊&#xff0c;不是直接就可以落户了吗&#xff1f;为什么大家都在说很难…

上海居住证转户口证攻略

2019独角兽企业重金招聘Python工程师标准>>> 一、居转户条件&#xff1a; 1.居住证满7年&#xff0c;社保满7年&#xff0c;税单满7年 2.最近3年连续社保是上海平均值2倍以上&#xff08;或者具备中级以上职称&#xff09; 3.自有产权房 二、居转户材料&#x…

2019非上海生源高校应届生落户指南

流程 一、计算积分基本要素导向要素用人单位要素 二、准备申请材料三、审核--证明信四、证明信-个人户口本落户社区公共户落户家庭户或者单位集体户口落户家庭户落户单位集体户口 博主从五月份准备落户申请材料&#xff0c;到十月中旬拿到上海个人户口本&#xff0c;历时五个月…

上海程序员落户攻略

上海居住证落户简称 “居转户” &#xff0c; 本文主要写给在上海打拼的程序员们&#xff0c;告诉大家比写代码更重要的一件事情是落户。讲述一些关于上海居住证落户的一些政策和一些建议。 很多人以为居转户&#xff0c;只要上海居住证满7年就可以转了&#xff0c;殊不知&…

上海落户计算机水平毕业研究生,2020年上海落户有哪些新规定?附研究生落户分值表!...

相信对于不少的年轻人来说&#xff0c;上海都是他们向往的城市&#xff0c;很多毕业生都在毕业后都希望可以留在上海&#xff0c;如果能够落户就再好不过了。下面小编就给大家说说2020年上海落户有哪些新规定&#xff0c;研究生如何落户&#xff0c;想了解的快来看看吧。 一、2…

2017年上海最新落户政策重磅出炉!你达标了吗?(明年就毕业了希望一切顺利)

2017年最新非上海户籍的应届毕业生落户标准公布&#xff0c; 应届毕业生落户标准分为72分&#xff01; 具体申请可根据2017《上海市居住证》和 居住证积分指南、申请本市户籍办法。 想想当初选择来魔都读书生活&#xff0c; 每天起早贪黑究竟为了什么&#xff1f; 很多人的“小…

【个人亲历】上海市人才引进落户最详细的流程记录说明

目录 一、材料准备 二、网上审核 2.1、预审上报 2.2、线下提供证明材料 2.3、初审、审核 2.4、公示 三、落户证明领取和准迁证查询 3.1、线下领取落户证明 3.2、准迁证查询 附&#xff1a;应用汇总&#xff1a; 从2022年6月领导通知我够资格人才引进落户以及2022…

2022留学生落户上海怎么办理社区公共户?

很多留学生会担心的一个问题是个人和直系亲属在沪无房产&#xff0c;且单位也无集体户怎么办呢? 其实无须担心&#xff0c;这种情况下可以按公安机关规定申请挂靠 社区公共户!简单而言 &#xff0c;就是租房在哪&#xff0c;就落户在相应的派出所。 落户通过后&#xff0c;留…

重磅!上海出落户新政:双一流应届硕士可直接落户!

点击上方“3D视觉工坊”&#xff0c;选择“星标” 干货第一时间送达 编辑丨科研大匠 9月23日&#xff0c;据上海学生就业创业服务网&#xff0c;上海市高校招生和就业工作联席会议制定的《2020年非上海生源应届普通高校毕业生进沪就业申请本市户籍评分办法》&#xff08;以下简…

上海落户条件—海归落户上海

上海落户条件—海归落户上海 国际留学生落户上海 2020年底&#xff0c;上海市政府发布上海落户2020新政改革&#xff0c;明确指出“基于国家户籍制度改革的新趋势&#xff0c;以及上海所面临的人才不足和各地人才竞争形势&#xff0c;对上海居住证转户籍人口提出一个基本的政策…