`
juji1010
  • 浏览: 117148 次
社区版块
存档分类
最新评论

转--一次HASH JOIN 临时表空间不足的分析和优化思路

 
阅读更多

最近遇到一个语句, 只要一执行这个语句就会出现报错临时表空间不足,回想一下在语句中用到临时表空间无非是大量的SORT和HASH,然后通过执行计划查看如下:
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3959216560

-------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | OMem | 1Mem | Used-Mem |
-------------------------------------------------------------------------------------------------------------------------------------------
| 1 | HASH UNIQUE | | 1 | 4 | 0 |00:00:00.01 | | | |
| 2 | NESTED LOOPS OUTER | | 1 | 4 | 0 |00:00:00.01 | | | |
|* 3 | HASH JOIN | | 1 | 4 | 0 |00:00:00.01 | 703K| 703K| |
| 4 | NESTED LOOPS OUTER | | 1 | 4 | 2524K|00:02:17.15 | | | |
| 5 | NESTED LOOPS | | 1 | 4 | 2524K|00:01:34.23 | | | |
|* 6 | HASH JOIN | | 1 | 4 | 2524K|00:00:53.84 | 2047M| 29M| 55M (1)|

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|* 7 | HASH JOIN | | 1 | 4 | 11M|00:01:00.03 | 2797K| 1148K| 3144K (0)|
|* 8 | TABLE ACCESS BY INDEX ROWID | T_COMMISSION_FEE | 1 | 25517 | 31948 |00:00:00.16 | | | |
|* 9 | INDEX RANGE SCAN | PK_T_COMMISSION_FEE | 1 | 25520 | 31948 |00:00:00.03 | | | |
|* 10 | HASH JOIN | | 1 | 33714 | 11M|00:00:12.24 | 1299K| 1299K| 1925K (0)|
|* 11 | TABLE ACCESS FULL | T_GL_BIZ_INTERFACE | 1 | 7889 | 12414 |00:00:00.10 | | | |
|* 12 | TABLE ACCESS FULL | T_BIZ_ACCOUNTING_INFO | 1 | 32696 | 63896 |00:00:00.27 | | | |
| 13 | VIEW | VW_NSO_1 | 1 | 3 | 2 |00:00:00.01 | | | |
|* 14 | FILTER | | 1 | | 2 |00:00:00.01 | | | |
|* 15 | CONNECT BY WITH FILTERING | | 1 | | 2 |00:00:00.01 | 9216 | 9216 | 8192 (0)|
| 16 | TABLE ACCESS BY INDEX ROWID| test| 1 | | 1 |00:00:00.01 | | | |
|* 17 | INDEX FULL SCAN | tes123| 1 | 1 | 1 |00:00:00.01 | | | |

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 18 | NESTED LOOPS | | 2 | | 1 |00:00:00.01 | | | |
| 19 | BUFFER SORT | | 2 | | 2 |00:00:00.01 | 9216 | 9216 | 8192 (0)|
| 20 | CONNECT BY PUMP | | 2 | | 2 |00:00:00.01 | | | |
|* 21 | INDEX RANGE SCAN | Ttest123| 2 | 3 | 1 |00:00:00.01 | | | |
| 22 | TABLE ACCESS FULL | test| 0 | 3 | 0 |00:00:00.01 | | | |
| 23 | TABLE ACCESS BY INDEX ROWID | test| 2524K| 1 | 2524K|00:00:30.72 | | | |
|* 24 | INDEX UNIQUE SCAN | test123| 2524K| 1 | 2524K|00:00:12.32 | | | |
| 25 | TABLE ACCESS BY INDEX ROWID | Ttt| 2524K| 1 | 2524K|00:00:31.35 | | | |
|* 26 | INDEX UNIQUE SCAN | tet1| 2524K| 1 | 2524K|00:00:12.00 | | | |
| 27 | TABLE ACCESS FULL | test31| 0 | 84 | 0 |00:00:00.01 | | | |
| 28 | TABLE ACCESS BY INDEX ROWID | tes1234| 0 | 1 | 0 |00:00:00.01 | | | |

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|* 29 | INDEX UNIQUE SCAN | PK_T_CONTRACT_MASTER | 0 | 1 | 0 |00:00:00.01 | | | |
-------------------------------------------------------------------------------------------------------------------------------------------

 

第6步太吓人了,我这个语句没有运行完因为会报错,这个状态应该是在故障点的,可以看到需要的HASH构造区域为2G,仔细分析下这个执行计划。
其实它是一个HASH JION和一个VIEW做的HASH JION,观察一下行数,就是11M(11*1024*1024)行和2行进行的一个HANSH JION,但是很奇怪的是执行
计划选择了大数据集为构造输入,构造输入在PGA的工作区的HASH_AREA_SIZE中建立一个HASH表,如果内存不够把HASH表存储在TMEP表空间里面,
而选择了小的数据集来作为探测输入,探测输入会通过连接条件通过HASH函数和HASH表进行比对,如果存在则输出,不存在则丢弃。下面我们通过
一个小小的试验来说明:
建立表
SQL> desc test;
Name Type Nullable Default Comments
----- ------------ -------- ------- --------
员工代码 NUMBER(20) Y
员工中文名 VARCHAR2(50) Y
员工英文名 VARCHAR2(50) Y
归属机构 VARCHAR2(50) Y
岗位名称 VARCHAR2(50) Y
SQL> select count(*) from test;

COUNT(*)
----------
3399680
这个是大数据集
建立表
SQL> desc test2
Name Type Nullable Default Comments
---- ---------- -------- ------- --------
员工代码 NUMBER(20) Y
工资 NUMBER(10) Y
SQL> select count(*) from test2;

COUNT(*)
----------
3
现在试验开始
首先执行语句
SQL> select count(*) from test a,test2 b where a.员工代码=b.员工代码;

COUNT(*)
----------
15360

已用时间: 00: 00: 09.12

执行计划
----------------------------------------------------------
0 SELECT STATEMENT ptimizer=ALL_ROWS (Cost=6098 Card=1 Bytes=
14)

1 0 SORT (AGGREGATE)
2 1 HASH JOIN (Cost=6098 Card=13197 Bytes=184758)
3 2 TABLE ACCESS (FULL) OF 'TEST2' (TABLE) (Cost=3 Card=3
Bytes=21)

4 2 TABLE ACCESS (FULL) OF 'TEST' (TABLE) (Cost=6063 Card=
3409202 Bytes=23864414)


可以看到这个时候小数据集作TEST2为了构造输入,在执行期间通过语句
select operation_id,operation_type,actual_mem_used,tempseg_size,tablespace
from v$session s,v$sql_workarea_active w
where s.sid=w.sid
and S.SID=151;
得出的结果如下:
OPERATION_ID OPERATION_TYPE ACTUAL_MEM_USED TEMPSEG_SIZE TABLESPACE
------------ ---------------------------------------- --------------- ------------ -------------------------------
2 HASH-JOIN 183296
HASH JION用于构造HASH表使用内存183K没有使用临时表空间。

现在我们通过HINT来改变大数据集和小数据集的顺序,执行语句如下:
SQL> select /*+ leading(a) use_hash(a b) */ count(*) from test a,test2 b where a.员工代码=b.员工代码;

COUNT(*)
----------
15360

已用时间: 00: 00: 13.82

执行计划
----------------------------------------------------------
0 SELECT STATEMENT ptimizer=ALL_ROWS (Cost=10636 Card=1 Bytes
=14)

1 0 SORT (AGGREGATE)
2 1 HASH JOIN (Cost=10636 Card=13197 Bytes=184758)
3 2 TABLE ACCESS (FULL) OF 'TEST' (TABLE) (Cost=6063 Card=
3409202 Bytes=23864414)

4 2 TABLE ACCESS (FULL) OF 'TEST2' (TABLE) (Cost=3 Card=3
Bytes=21)
这个时候TEST大数据集是构造输入,同样在执行期间通过语句得出结果
OPERATION_ID OPERATION_TYPE ACTUAL_MEM_USED TEMPSEG_SIZE TABLESPACE
------------ ---------------------------------------- --------------- ------------ -------------------------------
2 HASH-JOIN 1205248 18874368 TEMP
可以看到结果不同了,使用1.2M内存,使用临时表空间近19M。
同时如果我们关注下以下信息:
SQL> select * from v$sysstat where NAME LIKE '%workarea executions%';

STATISTIC# NAME CLASS VALUE STAT_ID
---------- ---------------------------------------------------------------- ---------- ---------- ----------
294 workarea executions - optimal 64 3525 3211650785
295 workarea executions - onepass 64 4 798730793
296 workarea executions - multipass 64 0 3804491469
现在我们运行
SQL> select /*+ leading(a) use_hash(a b) */ count(*) from test a,test2 b where a.员工代码=b.员工代码;

COUNT(*)
----------
15360
在运行
SQL> select * from v$sysstat where NAME LIKE '%workarea executions%';

STATISTIC# NAME CLASS VALUE STAT_ID
---------- ---------------------------------------------------------------- ---------- ---------- ----------
294 workarea executions - optimal 64 3525 3211650785
295 workarea executions - onepass 64 5 798730793
296 workarea executions - multipass 64 0 3804491469

可以看到workarea executions - onepass 增加了1说明我们进行了一次物理交换才完成了探测(还好没有多次)。

有了上面的试验,我的语句应该就可以通过HINT来改变小数据集为构造输入,而大数据集为探测输入来改变临时表空间不足的问题,同时提高性能。

分享到:
评论

相关推荐

    Oracle临时表空间不足和批处理缓慢问题探讨.pdf

    6. Hash Join 的作用:Hash Join 可以提高 SQL 语句的执行效率,但其也可能会消耗大量的临时表空间。 7. Oracle 数据库的性能优化:Oracle 数据库的性能优化需要从多方面入手,包括服务器硬件性能、操作系统设置、...

    MySQL临时表空间优化:提升数据库性能的关键

    需要注意的是,临时表空间的优化是一个持续的过程,需要根据实际业务需求和系统负载进行调整。希望本文能够帮助读者更好地理解和运用 MySQL 的临时表空间,从而提升数据库的处理能力和用户体验。

    通过分析SQL语句的执行计划优化SQL(九)

    在本文中,我们将深入探讨通过分析SQL语句的执行计划来优化JOIN的方法,特别是关注JOIN过程中的顺序和连接类型。 JOIN过程通常涉及两个row source(表),并且在大多数情况下,JOIN操作的步骤是串行的。尽管可以...

    Oracle数据库3种主要表连接方式对比

    如果内存不足,则可能需要使用临时表空间,进一步降低性能。 - 第一次返回结果的速度相对较慢,尤其是当需要从磁盘读取数据时。 ### 总结 每种连接方式都有其特定的应用场景: - **嵌套循环连接**适用于查询条件...

    MySQL数据库学习笔记(六)----MySQL多表查询之外键、表连接、子查询、索引

    例如,如果有一个学生表和课程表,学生表中的"course_id"可以作为外键,引用课程表的"course_id"主键,这样就能确保每个学生只能选择存在的课程。 接着,表连接(Table Join)是多表查询的常用方法。常见的连接类型...

    oracle表的连接方式

    - 如果表很大无法完全放入内存,优化器会将其分割成多个分区,并使用临时段进行I/O操作,此时需确保有足够的临时空间。 #### SORT MERGE JOIN SORT MERGE JOIN是一种基于排序的连接方法,通常包括三个步骤:对每个...

    ORACLE-排序优化[归纳].pdf

    4. 创造并监测临时表空间:合理分配和管理临时表空间,避免空间不足导致的排序问题。 了解在内存中执行排序的数量有助于优化资源分配,通过监控 PGA 的使用情况,可以发现排序操作对内存的需求,进而调整相关参数。...

    收获,不止SQL优化--抓住SQL的本质

    11.3.2 一次Hash Join 的 优化全过程 320 11.3.3 一次 Merge Sort Join 的优化全过程 324 11.3.4 一次统计信息收集不准确引发的NL性能瓶颈 329 11.4 本章习题、总结与延伸 332 第12章 动手,经典等价改写让SQL...

    收获不止SQL优化

    11.3.2 一次Hash Join 的 优化全过程 320 11.3.3 一次 Merge Sort Join 的优化全过程 324 11.3.4 一次统计信息收集不准确引发的NL性能瓶颈 329 11.4 本章习题、总结与延伸 332 第12章 动手,经典等价改写让SQL...

    ORACLE SQL性能优化规范

    - HASH JOIN:适用于大数据量的连接,当内存足够时,可以一次性加载所有数据进行比较。 - NESTED LOOP JOIN:对于小表驱动大表的情况,NLJ可以有效利用索引,但不适合大数据量。 - SORT MERGE JOIN:需要对参与JOIN...

    MySQL高级优化文档

    - **避免子查询**:考虑使用JOIN替代子查询,或通过临时表优化。 5. **存储引擎优化** - **InnoDB与MyISAM比较**:InnoDB支持事务和行级锁定,适合大量并发写操作;MyISAM则适用于读多写少的场景。 - **存储格式...

    空间数据库课件:第九章 关系系统及其查询优化.ppt

    这包括选择合适的索引策略、确定最佳的排序和分组方法、决定何时使用临时表等。物理优化通常基于成本模型,评估不同操作的成本,选择最低成本的执行计划。数据库管理系统会考虑各种因素,如I/O成本、CPU开销、内存...

    Oracle表连接方式

    优化器扫描小表(或数据源),利用连接键(也就是根据连接字段计算hash值)在内存中建立hash表,然后扫描大表,每读到一条记录就来探测hash表一次,找出与hash表匹配的行。当小表可以全部放入内存中,其成本接近全表...

    MySQL性能优化的21个最佳实践.zip

    8. **定期分析和优化表**:ANALYZE TABLE和OPTIMIZE TABLE命令可以帮助更新统计信息,优化存储空间。 9. **适当设置缓存和缓冲池**:增大innodb_buffer_pool_size以缓存数据和索引,减少磁盘I/O。 10. **避免...

    Oracle数据库性能优化浅析

    当排序所需空间超过`sort_area_size`参数设定的大小时,Oracle会在临时表空间进行磁盘排序,这比内存排序慢得多。 2. **合理设置参数**:通过调整`sort_area_size`等参数来优化排序过程,减少磁盘排序的发生。 3. **...

    redis集群, tomcat优化以及 MySQL5.6优化

    6. JOIN 优化:避免笛卡尔积,合理使用 INNER JOIN 和 OUTER JOIN,减少临时表的使用。 7. 表设计优化:采用正常化设计,减少冗余数据;考虑数据类型的选择,减少存储空间。 8. 使用慢查询日志:监控慢查询,找出...

Global site tag (gtag.js) - Google Analytics