生产环境sql语句调优实战第十篇

简介: 陆陆续续写了九篇关于生产环境sql语句的调优案例,发现了不少问题,可能有些问题回头来看是比较低级的错误,稍加改动就能够运行在秒级,有些可能是在秒级到毫秒级的小步提升等等,不管调优的改进多大,从dba的角度来看,好多问题都是基于资源来调优的,比如添加索引,降低IO,降低CPU消耗,提高CPU利用率等等。
陆陆续续写了九篇关于生产环境sql语句的调优案例,发现了不少问题,可能有些问题回头来看是比较低级的错误,稍加改动就能够运行在秒级,有些可能是在秒级到毫秒级的小步提升等等,不管调优的改进多大,从dba的角度来看,好多问题都是基于资源来调优的,比如添加索引,降低IO,降低CPU消耗,提高CPU利用率等等。如果有时候从业务角度来下下功夫,可能某种程度上效果要更好于基于资源/代价的调优。
最近客户反馈有几条sql语句IO消耗很高,希望我们能够给提点建议。
sql语句很短,但是运行时间在9秒左右。运行频率也是蛮高的。平均下来一个小时100次。
语句如下:
select product_name from service_details where subscriber_no in (select subscriber_no from subscriber where prim_resource_val = :1 and sub_status = 'A') and product_status = 'A' ;
其中service_details是一个亿级的大表,subscriber是百万级的表,但是 prim_resource_val字段不是索引列。所以导致subscriber表走了全表扫描。

Stat Name Statement Total Per Execution % Snap Total
Elapsed Time (ms) 5,304,719 9,558.05 0.88
CPU Time (ms) 1,806,243 3,254.49 0.87
Executions 555    
Buffer Gets 158,171,280 284,993.30 0.95
Disk Reads 158,091,403 284,849.37 4.60
Parse Calls 555 1.00 0.00
Rows 5,612 10.11  
User I/O Wait Time (ms) 3,351,159    
Cluster Wait Time (ms) 0    
Application Wait Time (ms) 4,142    
Concurrency Wait Time (ms) 0    
Invalidations 0    
Version Count 35    
Sharable Mem(KB) 818    
    
执行计划如下:
Plan hash value: 2174296646
-----------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                      |   126 |  4284 | 50533   (1)| 00:10:07 |
|   1 |  NESTED LOOPS                |                      |       |       |            |          |
|   2 |   NESTED LOOPS               |                      |   126 |  4284 | 50533   (1)| 00:10:07 |
|*  3 |     TABLE ACCESS FULL         | SUBSCRIBER           |    18 |   342 | 50517   (1)| 00:10:07 |
|*  4 |    INDEX RANGE SCAN          | SERVICE_DETAILS_PK   |     9 |       |     1   (0)| 00:00:01 |
|*  5 |   TABLE ACCESS BY INDEX ROWID| SERVICE_DETAILS      |     7 |   105 |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   3 - filter("PRIM_RESOURCE_VAL"=:1 AND "SUB_STATUS"='A')
   4 - access("SUBSCRIBER_NO"="SUBSCRIBER_NO")
   5 - filter("PRODUCT_STATUS"='A')

如果从资源代价的角度来看,一种思路是添加对应的索引。因为这个表是产品线中统一规划的。所以要加入索引还是很不容易的。
如果没有其它的调优思路,可能并行就是一把双刃剑了,相对来说速度会高一些,但是IO和CPU的消耗会比较高,对于执行如此频繁的语句来说使用多个并行可能对于系统负载时很高的。
看着sql语句比较简单,但是还没有立竿见影的效果也有些让人着急。数据库的角度的一些调整可能奏效不大,自己就想看看从业务角度能做点什么。
静下心来看看sql语句。
select product_name from service_details where subscriber_no in (select subscriber_no from subscriber where prim_resource_val = :1 and sub_status = 'A') and product_status = 'A' ;
sql语句中prim_resource_val就跟我们使用的手机号有些类似,这样一个号码为什么没有加入索引,从业务的角度来琢磨,可能是有做号码变更之类的操作的时候这个号码就会变化比较频繁。而保持不变的就是subscriber_no。就类似我们去银行办理业务的时候显示的客户号。这个字段就是主键列。
可能有的人有多个资源号的时候,打个比方,比如有机顶盒号,手机号等,在这个时候手机号就是主要的资源号。
这个时候再来分析为什么产品线中没有规划给resource_value作为索引列,也是考虑了后期的一些变更。这个列还是变化性比较大。这样考虑也就有一定的道理了。
因为对这部分的业务还比较熟悉,发现所需要的资源号,完全可以从一个独立的表中得到更完整的信息。subscriber_resource。
这个表尽管也是亿级的表,但是根据资源号来查找subscriber可以走index range scan。得到数据也要快很多。
subscriber_resource中存放着一个用户所使用的各类资源信息。从这个表里直接映射resource_value得到的用户信息就很有限了。因为根据条件是只需要激活状态的用户,那么我们完全可以在得到一个很简单的用户列表后直接来过滤用户状态就能得到所需要的信息了。最后做了如下的改动。把资源表关联进来。
select product_name 
  from service_details ser 
where subscriber_no in (select subscriber_no 
                          from subscriber 
                         where sub_status = 'A' 
                           and (subscriber_no, prim_resource_tp) in (select subscriber_no, resource_type from subcriber_resource where resource_value=:1) 
                           ) 
   and soc_status = 'A' 

先来看看执行计划,表面来看所走的索引还是比较高效的。
-----------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                | Name                   | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                         |                         |     7 |   196 |     7  (15)| 00:00:01 |       |       |
|   1 |  NESTED LOOPS                            |                         |       |       |            |          |       |       |
|   2 |   NESTED LOOPS                           |                         |     7 |   196 |     7  (15)| 00:00:01 |       |       |
|   3 |    VIEW                                  | VW_NSO_1                |     1 |    13 |     5   (0)| 00:00:01 |       |       |
|   4 |     HASH UNIQUE                          |                         |     1 |    36 |            |          |       |       |
|   5 |      NESTED LOOPS                        |                         |       |       |            |          |       |       |
|   6 |       NESTED LOOPS                       |                         |     1 |    36 |     5   (0)| 00:00:01 |       |       |
|   7 |        PARTITION RANGE ALL               |                         |     1 |    25 |     4   (0)| 00:00:01 |     1 |    11 |
|   8 |         TABLE ACCESS BY LOCAL INDEX ROWID| SUBSCRIBER_RESOURCE     |     1 |    25 |     4   (0)| 00:00:01 |     1 |    11 |
|*  9 |          INDEX RANGE SCAN                | SUBSCRIBER_RESOURCE_1IX |     1 |       |     3   (0)| 00:00:01 |     1 |    11 |
|* 10 |        INDEX UNIQUE SCAN                 | SUBSCRIBER_PK           |     1 |       |     1   (0)| 00:00:01 |       |       |
|* 11 |       TABLE ACCESS BY INDEX ROWID        | SUBSCRIBER              |     1 |    11 |     1   (0)| 00:00:01 |       |       |
|* 12 |    INDEX RANGE SCAN                      | SERVICE_DETAILS_PK      |     9 |       |     1   (0)| 00:00:01 |       |       |
|* 13 |   TABLE ACCESS BY INDEX ROWID            | SERVICE_DEAILS          |     7 |   105 |     1   (0)| 00:00:01 |       |       |
-----------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   9 - access("RESOURCE_VALUE"=:1)
  10 - access("SUBSCRIBER_NO"="SUBSCRIBER_NO")
  11 - filter("SUB_STATUS"='A' AND "PRIM_RESOURCE_TP"="RESOURCE_TYPE")
  12 - access("SUBSCRIBER_NO"="SUBSCRIBER_NO")
  13 - filter("PRODUCT_STATUS"='A')  

最后在备份库做相关的测试,执行时间都在毫秒级。
所以有些时候业务的角度来调优可能会有意向不到的收获。还有几个类似的语句,执行时间在分钟级,调整成类似的形式之后,都在毫秒级就完成了数据查询。






目录
相关文章
|
SQL 运维 监控
SQL查询太慢?实战讲解YashanDB SQL调优思路
本文是Meetup第十期“调优实战专场”的第二篇技术文章,上一篇《高效查询秘诀,解码YashanDB优化器分组查询优化手段》中,我们揭秘了YashanDB分组查询优化秘诀,本文将通过一个案例,助你快速上手YashanDB慢日志功能,精准定位“慢SQL”后进行优化。
|
SQL 关系型数据库 MySQL
大数据新视界--大数据大厂之MySQL数据库课程设计:MySQL 数据库 SQL 语句调优方法详解(2-1)
本文深入介绍 MySQL 数据库 SQL 语句调优方法。涵盖分析查询执行计划,如使用 EXPLAIN 命令及理解关键指标;优化查询语句结构,包括避免子查询、减少函数使用、合理用索引列及避免 “OR”。还介绍了索引类型知识,如 B 树索引、哈希索引等。结合与 MySQL 数据库课程设计相关文章,强调 SQL 语句调优重要性。为提升数据库性能提供实用方法,适合数据库管理员和开发人员。
|
关系型数据库 MySQL 大数据
大数据新视界--大数据大厂之MySQL 数据库课程设计:MySQL 数据库 SQL 语句调优的进阶策略与实际案例(2-2)
本文延续前篇,深入探讨 MySQL 数据库 SQL 语句调优进阶策略。包括优化索引使用,介绍多种索引类型及避免索引失效等;调整数据库参数,如缓冲池、连接数和日志参数;还有分区表、垂直拆分等其他优化方法。通过实际案例分析展示调优效果。回顾与数据库课程设计相关文章,强调全面认识 MySQL 数据库重要性。为读者提供综合调优指导,确保数据库高效运行。
|
SQL Java 数据库连接
如何在 Java 代码中使用 JSqlParser 解析复杂的 SQL 语句?
大家好,我是 V 哥。JSqlParser 是一个用于解析 SQL 语句的 Java 库,可将 SQL 解析为 Java 对象树,支持多种 SQL 类型(如 `SELECT`、`INSERT` 等)。它适用于 SQL 分析、修改、生成和验证等场景。通过 Maven 或 Gradle 安装后,可以方便地在 Java 代码中使用。
5198 11
|
存储 SQL 关系型数据库
【MySQL调优】如何进行MySQL调优?从参数、数据建模、索引、SQL语句等方向,三万字详细解读MySQL的性能优化方案(2024版)
MySQL调优主要分为三个步骤:监控报警、排查慢SQL、MySQL调优。 排查慢SQL:开启慢查询日志 、找出最慢的几条SQL、分析查询计划 。 MySQL调优: 基础优化:缓存优化、硬件优化、参数优化、定期清理垃圾、使用合适的存储引擎、读写分离、分库分表; 表设计优化:数据类型优化、冷热数据分表等。 索引优化:考虑索引失效的11个场景、遵循索引设计原则、连接查询优化、排序优化、深分页查询优化、覆盖索引、索引下推、用普通索引等。 SQL优化。
2663 15
【MySQL调优】如何进行MySQL调优?从参数、数据建模、索引、SQL语句等方向,三万字详细解读MySQL的性能优化方案(2024版)
|
SQL 数据库 UED
SQL性能提升秘籍:5步优化法与10个实战案例
在数据库管理和应用开发中,SQL查询的性能优化至关重要。高效的SQL查询不仅可以提高应用的响应速度,还能降低服务器负载,提升用户体验。本文将分享SQL优化的五大步骤和十个实战案例,帮助构建高效、稳定的数据库应用。
1715 3
|
SQL Oracle 关系型数据库
Oracle SQL:了解执行计划和性能调优
Oracle SQL:了解执行计划和性能调优
653 1
|
SQL 数据处理 数据库
SQL语句优化与查询结果优化:提升数据库性能的实战技巧
在数据库管理和应用中,SQL语句的编写和查询结果的优化是提升数据库性能的关键环节
1325 0
|
SQL 关系型数据库 MySQL
sql注入原理与实战(三)数据库操作
sql注入原理与实战(三)数据库操作
sql注入原理与实战(三)数据库操作
|
SQL 缓存 监控
SQL性能提升指南:五大优化策略与十个实战案例
在数据库性能优化的世界里,SQL优化是提升查询效率的关键。一个高效的SQL查询可以显著减少数据库的负载,提高应用响应速度,甚至影响整个系统的稳定性和扩展性。本文将介绍SQL优化的五大步骤,并结合十个实战案例,为你提供一份详尽的性能提升指南。
1952 0