一条SQL直接跑崩288核,1.5T内存数据库

最近遇到一个Oracle的SQL语句引发的线上故障,数据库服务被重启。主机288核,1.5T也没抗住。

复制代码
select  count(*) from dev_db.t1 t1,dev_db.t2 t2 where t1.object_name = t2.object_name or t1.DATA_OBJECT_ID = t2.DATA_OBJECT_ID and t1.OBJECT_ID = 123 and rownum = 1;
--------------------------------------------------------------------------------
| Id  | Operation               | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |      |     1 |    77 |    31M  (1)| 00:20:50 |
|   1 |  SORT AGGREGATE         |      |     1 |    77 |            |          |
|   2 |   COUNT                 |      |       |       |            |          |
|*  3 |    FILTER               |      |       |       |            |          |
|   4 |     MERGE JOIN CARTESIAN|      |  6131M|   439G|    31M  (1)| 00:20:50 |
|   5 |      TABLE ACCESS FULL  | T1   | 78306 |  3135K|   411   (1)| 00:00:01 |
|   6 |      BUFFER SORT        |      | 78307 |  2752K|    31M  (1)| 00:20:50 |
|   7 |       TABLE ACCESS FULL | T2   | 78307 |  2752K|   409   (1)| 00:00:01 |
--------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("T1"."OBJECT_NAME"="T2"."OBJECT_NAME" OR
              "T1"."DATA_OBJECT_ID"="T2"."DATA_OBJECT_ID" AND "T2"."DATA_OBJECT_ID"
              IS NOT NULL AND "T1"."DATA_OBJECT_ID" IS NOT NULL AND
              "T1"."OBJECT_ID"=123 AND ROWNUM=1)

在执行计划中看到步骤4产生了笛卡尔积连接,成本相当的高,这两个表仅有7万行数据,执行时间超过了5分钟。

数据库中关于NOT、AND、OR的逻辑运算优先级就是按这个顺序进行的,判断是开发人员失误造成的。下面是经过优化后的执行计划。

复制代码
select  count(*) from dev_db.t1 t1,dev_db.t2 t2 where (t1.object_name = t2.object_name or t1.DATA_OBJECT_ID = t2.DATA_OBJECT_ID) and t1.OBJECT_ID = 123 and rownum = 1;
-----------------------------------------------------------------------------
| Id  | Operation            | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |      |     1 |    77 |   822   (1)| 00:00:01 |
|   1 |  SORT AGGREGATE      |      |     1 |    77 |            |          |
|*  2 |   COUNT STOPKEY      |      |       |       |            |          |
|   3 |    NESTED LOOPS      |      |     1 |    77 |   822   (1)| 00:00:01 |
|*  4 |     TABLE ACCESS FULL| T1   |     1 |    41 |   411   (1)| 00:00:01 |
|*  5 |     TABLE ACCESS FULL| T2   |     1 |    36 |   411   (1)| 00:00:01 |
-----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter(ROWNUM=1)
   4 - filter("T1"."OBJECT_ID"=123)
   5 - filter("T1"."OBJECT_NAME"="T2"."OBJECT_NAME" OR
              "T2"."DATA_OBJECT_ID" IS NOT NULL AND
              "T1"."DATA_OBJECT_ID"="T2"."DATA_OBJECT_ID" AND "T1"."DATA_OBJECT_ID"
              IS NOT NULL)

在这个执行计划中,t1表作为驱动表,过滤条件是object_id=123,线上这个条件是主键,因为懒没有创建这个主键,所以是全表扫描。

t2表作为被驱动表只匹配到了一条数据。因为STOPKEY的优化,在取到一条数据后SQL停止,无需扫描全部数据,因此执行时间非常短。

总结

本次问题原因是因为一个逻辑运算的优先级判断错误,以至于数据库资源被使用完导致数据库节点被重启。

对于自己拿不准的SQL语句,查阅官方文档是最权威的参考依据。

其次,在测试环境就算只有少量数据也可以看到执行计划是否合理。

最后,上线时SQL语句经过把关,可以最大限度减少SQL语句引发的线上故障。

相关推荐
码云数智-大飞5 小时前
Oracle RAS:AI时代守护企业数据安全的智能盾牌
数据库·人工智能·oracle
Root_Hacker8 小时前
sql注入学习笔记
数据库·sql·web安全·网络安全·oracle·网络攻击模型
IT邦德8 小时前
基于OEL8环境的图形化部署Oracle26ai
数据库·oracle
一心赚狗粮的宇叔8 小时前
mongosDb 安装及Mongosshell常见命令
数据库·mongodb·oracle·nosql·web·全栈
hamawari9 小时前
SQL语法
数据库·sql·oracle
小北方城市网9 小时前
Spring Boot 多数据源与事务管理实战:主从分离、动态切换与事务一致性
java·开发语言·jvm·数据库·mysql·oracle·mybatis
Remember_99311 小时前
Spring 事务深度解析:实现方式、隔离级别与传播机制全攻略
java·开发语言·数据库·后端·spring·leetcode·oracle
中二病码农不会遇见C++学姐13 小时前
《文明6》Mod开发实战:从游戏日志定位和解决Mod加载问题
数据库·游戏·oracle
石头wang1 天前
oracle jdbc 依赖以及对dbeaver的性能影响,如何选择oracle驱动, oracle jdbc 驱动
数据库·oracle