【演讲实录】RWP团队谈SQL优化

简介:

设定一个高的目标

abd8bfa62e92ee3355887b862298d6aa2b8ec74b

如果您把一个SQL从一个小时优化到了1分钟,您会停止工作吗?会不会考虑是否能给它优化到1秒钟? 

工作中,每个人都有压力,压力之下,很容易疏于思考。一个SQL多长时间能跑完,依赖于它跑在什么样的硬件和软件环境上。一个SQL能不能跑的更快,本质上是:它是否能够更加充分的利用硬件资源和软件能力。 

做SQL优化,给自己设定一个高的目标非常重要!

去优化那些好的SQL

0918a0538827cc79aa4d33b1176a0f7acbd9e4c1

有了高的目标,接下来,还要找到那些好的SQL进行优化。那么,什么是好的SQL?

(1)有效的 SQL

数据库是为了执行SQL设计的,不是为了一执行就报错的无效SQL设计的。

如果执行一个SQL,报ORA的错误,那么这是一个无效的SQL,它不应该存在于您的系统里面,当然更不应该成为您优化的对象。

如果执行一个SQL,报ORA的错误,那么在数据库里面会是一个failure parse。如果您系统的AWR报告里面有failure parse,那么您要注意了,后果可能很严重。

(2)您知道业务含义的SQL

有很多时候,一些SQL和PL/SQL存储过程是根本就不需要被执行的。但是由于种种原因,那些SQL和PL/SQL存储过程存在在系统中,可能都已存在了很长时间,写那些SQL和PL/SQL存储过程的人可能早就跳槽了,为了所谓的“稳定”,没有人去动那些SQL和PL/SQL存储过程。去优化这些根本就不需要被执行的SQL和PL/SQL存储过程当然是没有任何意义的。 

所以,在优化任何一条SQL之前,应该首先知道那条SQL业务上的含义,确定它确实是需要被执行的,再去优化它。

(3)构造好的SQL

如果一个SQL语句里面有IN列表,IN列表里面有几百个值,那么那几百个值,很有可能是来源于另外一个SQL,而非人工输入。由于IN列表中值的个数有一个允许的上限,有些SQL甚至会长成下面的样子:

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy

几百几千几万个值在IN列表里面,那是不是SQL构造的不好,是不是应该先将它改成一个JOIN再去考虑其他?

(4)没有编写错误的SQL

N个表做JOIN的话,一般情况应该有N-1个JOIN条件。如果JOIN条件小于N-1个的话,就会有CARTESIAN JOIN出现,结果集里面会有重复值。在SELECT LIST里面加上DISTINCT,通常就可以使得SQL得到功能上正确的结果集。这就好比您去银行取钱,实际只要取1000块钱,可是您先取了2000块钱,再把余下的1000存回去,多此一举,虽然实际结果是对的,您确实是取了1000块钱。

当SQL处理的数据量小的时候,这个多此一举对于响应时间的影响并不会很大。可是当SQL处理的数据量大的时候,这个影响就会完全凸显出来。还是那个取钱的例子,如果您实际只要取1000块钱,可是您先取了10001000块钱,再把余下的10000000块钱存回去。最后您也会得到1000块钱,可是银行员工为您取钱的时候数出10001000块钱的时间,和把钱存回去的时候再数好10000000块钱的时间,都是您办业务的时间,您取钱的时间就会变得相当长了。

SQL语句中WHERE条件里面的值的数据类型,应该与相应的列的数据类型一致。否则SQL语句虽不会报错,会隐式的用函数将那个列转换成与相应的值的数据类型一致,去执行SQL。这种隐式数据类型转换,可能会导致ORA-01722的错误,可能会导致相应的列上的索引不能被使用到,可能会导致明明可以使用分区裁剪但却用不上的情况,响应时间可能差好几个数量级。

给SQL一个好的执行环境

e2d22f9018f32e3b61dfeecacc337c8b7b81e648

SQL需要在好的环境上执行才能够性能好。那么什么是好的执行环境呢?

正确的给软件打上补丁,是打造好的执行环境的第一步。明明您都花了钱买软件,明明人家软件厂家都出了补丁可以让软件跑的更好更快,为什么不打补丁呢?当然了,打补丁是个技术活,怎么正确的给软件打上补丁,肯定是要按照软件厂家的说明来,或者咨询软件厂家啦。

使用默认的init.ora参数设置,也是打造好的执行环境的重要一环。使用默认的init.ora参数设置,意味着您是按照Oracle内部研发团队设计软件的方法去使用它,意味着您使用的是经过Oracle内部测试团队严格测试的软件。当然了,有一些特定的应用软件,比如Oracle的EBS,要求修改init.ora参数,这种情况是要修改,因为那些修改是经过应用软件厂家严格测试过的。

如果是因为遇到bug,需要修改某些参数做为临时解决方案,那么当那个bug修复之后,您应该及时将相应的参数改回去,否则后果可能也会很严重噢。

另外,若随意修改init.ora参数,可能会导致售后的问题。

从数据库设计的角度优化SQL

b3d35a1a95139a38577490390d2c68324b495506

现在Oracle数据库软件使用的是Cost Based Optimizer(CBO),基于成本的优化器。

本质上来讲,优化器就是一系列的算法。优化器会接受输入的信息来生成SQL的执行计划。输入的信息包括: 

(1)统计信息

统计信息包括两个方面,系统的统计信息,和实际用户数据的统计信息。

系统的统计信息,推荐大家使用默认设置。实际用户数据的统计信息,最重要的是要有代表性,要能够反应数据的特征。

(2)约束

NOT NULL, PK, FK, UK等等约束,若实际数据是需要符合约束的,那么那些约束应该存在于数据库里面,应该让优化器知道这些约束的存在。

举个例子。多个表做JOIN,如果某张表只是被JOIN了,比如下面这样事儿的

0433ec36e60b2dbcc59c2a87ddbd5adaf9206605

customer表只出现在了JOIN部分,但是并没有出现在SELECTlist里面,也没有出现在查询条件里面,也没有出现在GROUP BY和ORDER BY的部分里面。那么如果lineorder表上的JOIN key(lo_custkey)上存在外键约束的话,优化器就会知道lo_custkey = c_custkey这个JOIN总是能够JOIN的上,那么在实际执行的时候就不会去JOIN customer这个表了。

执行计划可以是下面这样事儿的:

bc2de7193e8b257267ef81f3f2691f89d66c666b

您擦亮双眼看好了么,customer表压根儿就没有出现在执行计划里面!您能做的最快的JOIN就是不JOIN啊哈哈哈。这种情况我们叫做JOIN elimination,发生的前提条件是相关约束的存在。

(3)Schema设计

Schema的设计,包括数据模型,索引,分区,压缩,clustering(数据根据相应的KEY值物理上存放在一起)等等,对SQL性能都有非常重要的影响。 

有些SQL里面,一个表和自己JOIN几十次,就是因为数据模型设计得不好导致的。此时若只是专注于SQL本身,能够取得的性能提升恐怕就非常有限了。

Schema设计是门大学问,每一个方面都可以对SQL的性能有几个数量级的影响。想做好SQL优化的话,您必须要将schema设计重视起来。

从执行角度优化SQL

00e3a9e082db0050679c1e68c7eaebf784b07754

从执行的角度去优化SQL,主要是要考虑以下方面: 

  • Access method,是通过索引访问数据,还是全表扫描。
  • Join方法,是Nested Loop Join,Hash Join,还是Merge Join。
  • Join顺序,是表A Join表B,再Join表C,还是反之。
  • 并行执行时,生产者进程组和消费者进程组之间的数据分发方法,是hash,还是broadcast,还是其他的分发方法。
  • 数据是否有倾斜,是否某些KEY值对应的数据特别多,其他KEY值对应的数据特别少。
原文发布时间为:2018-01-09
本文作者:Christine Qu
本文来自云栖社区合作伙伴“数据和云”,了解相关信息可以关注“ 数据和云 ”微信公众号
相关文章
|
6天前
|
SQL 缓存 Java
sql优化方法
sql优化方法
24 0
|
6天前
|
SQL 存储 关系型数据库
一文搞懂SQL优化——如何高效添加数据
**SQL优化关键点:** 1. **批量插入**提高效率,一次性建议不超过500条。 2. **手动事务**减少开销,多条插入语句用一个事务。 3. **主键顺序插入**避免页分裂,提升性能。 4. **使用`LOAD DATA INFILE`**大批量导入快速。 5. **避免主键乱序**,减少不必要的磁盘操作。 6. **选择合适主键类型**,避免UUID或长主键导致的性能问题。 7. **避免主键修改**,保持索引稳定。 这些技巧能优化数据库操作,提升系统性能。
294 4
一文搞懂SQL优化——如何高效添加数据
|
6天前
|
SQL 存储 关系型数据库
SQL优化之Explain详解(mysql)
`Explain`是MySQL中用于分析SQL查询执行计划的工具。它可以帮助我们了解MySQL如何执行SQL语句,包括如何使用索引、预计的行数以及查询的顺序。以下是`Explain`输出的关键列及其含义的简要摘要: 1. **id**:查询的序列号,表示查询中的子句层次,id越大优先级越高。 2. **select_type**:表示查询的类型,如SIMPLE(简单查询)、PRIMARY(主查询,多表查询中的第一个查询)、SUBQUERY(子查询)、DERIVED(派生表)或UNION(UNION操作的查询部分)。 3. **table**:查询涉及的表名,如果是子查询,可能显示为衍生表
37 0
|
6天前
|
SQL 关系型数据库 MySQL
项目中遇到一张900w的数据表把原先要花费17s执行的SQL优化到300ms经验加100哈哈哈
项目中遇到一张900w的数据表把原先要花费17s执行的SQL优化到300ms经验加100哈哈哈
25 1
|
6天前
|
SQL 存储 关系型数据库
【MySQL】SQL 优化
【MySQL】SQL 优化
23 0
|
6天前
|
SQL 缓存 关系型数据库
一次sql改写优化子查询的案例
在生产环境中,一个MySQL RDS实例遭遇了高CPU使用率问题,原因是执行了一条复杂的UPDATE SQL语句,该语句涉及一个无法缓存的子查询(UNCACHEABLE SUBQUERY),导致子查询需要针对每一行数据重复执行,极大地影响了性能。SQL语句的目标是更新一行数据,但执行时间长达30秒。优化方法是将子查询转换为内连接形式,优化后的语句执行时间降低到毫秒级别,显著减少了CPU消耗。通过示例数据和执行计划对比,展示了优化前后的时间差异和执行效率的提升。
|
6天前
|
存储 SQL 关系型数据库
掌握高性能SQL的34个秘诀🚀多维度优化与全方位指南
掌握高性能SQL的34个秘诀🚀多维度优化与全方位指南
|
6天前
|
SQL 存储 关系型数据库
【MySQL系列笔记】SQL优化
SQL优化是通过调整数据库查询、索引、表结构和配置参数等方式,提高SQL查询性能和效率的过程。它旨在减少查询执行时间、减少系统资源消耗,从而提升数据库系统整体性能。优化方法包括索引优化、查询重写、表分区、适当选择和调整数据库引擎等。
237 3
|
6天前
|
存储 SQL 缓存
30个业务场景的SQL优化
这些优化策略和示例可以帮助改善 `SQL` 查询的性能和效率。在实践中,需要综合考虑数据库设计、`SQL` 编写、服务器配置等多方面因素,选择合适的优化方法,并进行充分的测试和验证。以上 30 个经验是 V 哥在实际经验中总结的内容,当然,业务场景不同,具体的优化策略也会不同,按实际情况处理,这不就是程序员要做的事情么。
|
6天前
|
SQL 存储 算法
clickhouse SQL优化
clickhouse 是 OLAP 数据库,但其具有独特的索引设计,所以如果拿 MySQL 或者其他 RDB 的优化经验来优化 clickhouse 可能得不到很好的效果,所以特此单独整理一篇文档,用于有 SQL 优化需求的同学,本人接触 clickhouse 时间也不长,难免有不足的地方,如果大家发现错误,还请不吝指正。