当前位置: 首页 > 面试题库 >

Oracle中临时数据的性能注意事项

东方吕恭
2023-03-14
问题内容

我正在评估各种选项,以便针对Oracle中的单个临时数据集运行一堆高性能查询。在T-
SQL中,我可能会使用内存中的临时表,但是Oracle没有与此功能完全相同的功能。

我目前看到这些选项:

1.全局临时表

CREATE GLOBAL TEMPORARY TABLE test_temp_t (
  n NUMBER(10), 
  s VARCHAR2(10)
) ON COMMIT DELETE ROWS; -- Other configurations are possible, too

DECLARE
  t test_t;
  n NUMBER(10);
BEGIN

  -- Replace this with the actual temporary data set generation
  INSERT INTO test_temp_t
  SELECT MOD(level, 10), '' || MOD(level, 12)
  FROM dual
  CONNECT BY level < 1000000;

  -- Replace this example query with more interesting statistics
  SELECT COUNT(DISTINCT t.n)
  INTO n 
  FROM test_temp_t t;

  DBMS_OUTPUT.PUT_LINE(n);
END;

计划:

----------------------------------------------------
| Id  | Operation            | A-Rows |   A-Time   |
----------------------------------------------------
|   0 | SELECT STATEMENT     |      1 |00:00:00.27 |
|   1 |  SORT AGGREGATE      |      1 |00:00:00.27 |
|   2 |   VIEW               |     10 |00:00:00.27 |
|   3 |    HASH GROUP BY     |     10 |00:00:00.27 |
|   4 |     TABLE ACCESS FULL|    999K|00:00:00.11 |
----------------------------------------------------

2.取消PL / SQL表类型变量的嵌套

CREATE TYPE test_o AS OBJECT (n NUMBER(10), s VARCHAR2(10));
CREATE TYPE test_t AS TABLE OF test_o;

DECLARE
  t test_t;
  n NUMBER(10);
BEGIN

  -- Replace this with the actual temporary data set generation
  SELECT test_o(MOD(level, 10), '' || MOD(level, 12))
  BULK COLLECT INTO t
  FROM dual
  CONNECT BY level < 1000000;

  -- Replace this example query with more interesting statistics
  SELECT COUNT(DISTINCT n)
  INTO n 
  FROM TABLE(t) t;

  DBMS_OUTPUT.PUT_LINE(n);
END;

计划:

------------------------------------------------------------------
| Id  | Operation                          | A-Rows |   A-Time   |
------------------------------------------------------------------
|   0 | SELECT STATEMENT                   |      1 |00:00:00.68 |
|   1 |  SORT GROUP BY                     |      1 |00:00:00.68 |
|   2 |   COLLECTION ITERATOR PICKLER FETCH|    999K|00:00:00.22 |
------------------------------------------------------------------

3.物化视图

对于这个用例,我将它们排除在外,因为所讨论的临时数据集相当复杂,并且对更新实例化视图的影响将太大。

实际数据注意事项

以上是我正在尝试执行的示例。实际的数据集包括:

  • 临时数据从大约15个联接表中反规范化。
  • 它的产生速度约为2-20x /秒。
  • 每个临时数据集的实际行数约为10-200(不如上面的示例大)。
  • 系统的每个用户都有自己的临时数据集(总共1M个用户,10k个并发用户)。
  • 建立数据集后,应针对该数据集进行大约10-50次分析查询。
  • 这些分析必须在线运行,即不能将其推迟到批处理作业中。

问题

根据我的直觉,临时表查询 “应该” 比较慢,因为它(可能)涉及I / O和磁盘访问,而PL /
SQL集合查询仅仅是内存中的解决方案。但是在我的琐碎基准测试中,情况并非如此,因为临时表查询比PL / SQL集合查询高出3倍。为什么会这样呢?是否发生PL
/ SQL <-> SQL上下文切换?

对于定义良好的临时数据集,我是否还有其他选择可以进行快速(但仍广泛)的“内存中”数据分析?有没有比较各种选择的重要的公开基准?


问题答案:

由于具有缓存和异步I / O,临时表实际上与内存表相同,并且临时表解决方案不需要任何开销即可在SQL和PL / SQL之间进行转换。

确认结果

将这两个版本与RunStats进行比较,临时表版本 看起来 要差得多。对于Run1中的临时表版本,所有这些垃圾,而对于Run2中的PL /
SQL版本,只剩下一点额外的内存。起初,PL / SQL似乎应该是明显的赢家。

Type  Name                              Run1 (temp) Run2 (PLSQL)         Diff
----- -------------------------------- ------------ ------------ ------------
...
STAT  physical read bytes                    81,920            0      -81,920
STAT  physical read total bytes              81,920            0      -81,920
LATCH cache buffers chains                  104,663          462     -104,201
STAT  session uga memory                    445,488      681,016      235,528
STAT  KTFB alloc space (block)            2,097,152            0   -2,097,152
STAT  undo change vector size             2,350,188            0   -2,350,188
STAT  redo size                           2,804,516            0   -2,804,516
STAT  temp space allocated (bytes)       12,582,912            0  -12,582,912
STAT  table scan rows gotten             15,499,845            0  -15,499,845
STAT  session pga memory                    196,608   19,857,408   19,660,800
STAT  logical read bytes from cache     299,958,272            0 -299,958,272

但是在一天结束时,只有挂钟时间很重要。临时表的加载和查询步骤都快得多。

在PL / SQL版本可以通过更换得到改善BULK COLLECTcast(collect(test_o(MOD(a, 10), '' || MOD(a, 12))) as test_t) INTO t。但是它仍然比临时表版本慢得多。

优化阅读

从小型临时表读取仅使用内存中的缓冲区高速缓存。仅多次运行查询部分,并观察consistent gets from cache(内存)在physical reads cache(磁盘)保持不变的情况下如何增加。

select name, value
from v$sysstat
where name in ('db block gets from cache', 'consistent gets from cache', 
'physical reads cache');

优化写入

理想情况下,将没有物理I / O,尤其是由于临时表为ON COMMIT DELETE ROWS。听起来,Oracle的下一版本可能会引入这样的机制。但是在这种情况下,它并不重要,磁盘I / O似乎并不会减慢速度。

多次运行加载步骤,然后运行select * from v$active_session_history order by sample_time desc;。大多数I / O是BACKGROUND,这意味着没有任何等待。我假设临时表内部逻辑只是常规DML机制的副本。通常,如果已提交新表数据,则
可能 需要将其写入磁盘。Oracle可能会开始处理它,例如通过将数据从日志缓冲区移到磁盘上,但是在出现实际情况之前,不要急于进行COMMIT

PL / SQL时间流向何方?

我没有线索。在SQL和PL / SQL引擎之间是否存在多个上下文切换或单个转换?据我所知,没有可用的指标显示在SQL和PL / SQL之间切换所花费的
时间

我们可能永远无法确切知道为什么PL /
SQL代码比较慢。我不用担心太多。普遍的答案是,无论如何,绝大多数数据库工作都必须使用SQL进行。如果甲骨文花了更多的时间优化数据库核心SQL而不是附加语言PL
/ SQL,这将很有意义。

附加条款

对于性能测试,将connect by逻辑删除到一个单独的步骤中可能会有所帮助。该SQL是加载数据的绝妙技巧,但它可能非常缓慢且占用大量资源。用这种技巧一次加载一个样本表,然后从该表中插入更为现实。

我尝试使用新的Oracle 12c功能(临时撤消)和新的18c功能(私有临时表)。两者都没有比常规临时表提高性能。

我不会打赌,但是我可以看到一种结果,随着数据变大,结果将完全改变。日志缓冲区和缓冲区高速缓存只能变大。最终,该后台I /
O可能加起来并淹没了某些进程,从而将BACKGROUND等待变为FOREGROUND等待。另一方面,PL /
SQL解决方案只有这么多的PGA内存,然后崩溃。

最后,这部分证实了我对“内存数据库”的怀疑。缓存并不是什么新鲜事物,数据库已经做了数十年了。



 类似资料:
  • C++ 程序员偏爱性能,所以这里是一个性能专题。 由于 Hana 运行时和编译时计算处于前沿领域,我们不仅对运行时性能感兴趣,而且对编译时性能也感兴趣。 由于这两个主题是相当不相交的,我们在下面分别对待。 注意: 当我们推送到存储库时,本节中提供的基准会自动更新。 如果您发现不能承受此处声明的结果,请开一个GitHub issue; 它可能是一个性能回归。 警告: 在写这篇文章的时候,并不是所有的

  • 问题内容: 我有一个需要从我的Java程序调用的功能。我曾经将参数传递给存储的proc。我正在使用oracle瘦驱动程序(在Web逻辑服务器中根据相关的jndi条目配置)。此存储的proc没有任何OUT值。此存储的proc接受一个数字值,并根据接收到的值在db中进行很多更新。 我得到一个连接对象,然后在循环中调用此存储的proc(20次传递20个数字)。当我直接从oracle客户端调用此存储的pr

  • 问题内容: 所有, 谁能让我确切知道两者之间的性能问题?站点:CodeRanch简要概述了使用keySet()和get()时需要的内部调用。但是如果使用keySet()和get()方法时,任何人都可以提供有关流的确切详细信息,那将是很好的。这将帮助我更好地了解性能问题。 问题答案: 首先,这完全取决于您使用的地图类型。但是,由于JavaRanch线程讨论了HashMap,因此我假设这就是您所指的实

  • 问题内容: 我无法调试出现在一周前的消息。 我尝试还原到旧文件,但这很奇怪,没有任何解决方案可以解决我的问题。 因此:我有两个长时间的轮询请求。(关闭其中之一没有帮助)。 例如,这是其中之一: 如您所见,我发送了缓存控制标头,因此这应该不是这里描述的问题, 我也没有安装任何adBlocker,这是本地安装。 有一个客户端脚本 这正常吗?我不能将其作为长时间轮询的正常消息-因为它是待处理的请求。它似

  • 本文向大家介绍Oracle数据库服务器修改操作系统时间的注意事项详解,包括了Oracle数据库服务器修改操作系统时间的注意事项详解的使用技巧和注意事项,需要的朋友参考一下 Oracle 数据库服务器修改操作系统时间的注意事项: 对单机或者ha 1.对数据库本身而言,其实是没有影响的。因为scn不依赖于os时间 2.对app(应用程序)而言,若是app中使用了sysdate之类的,那确实是有影响的。

  • 本文向大家介绍asp中使用MSXML2.DOMDocument处理XML数据时的注意事项,包括了asp中使用MSXML2.DOMDocument处理XML数据时的注意事项的使用技巧和注意事项,需要的朋友参考一下 asp使用MSXML2.DOMDocument加载网络上的xml文件时,在调用load方法前需要注意设置: 即启用ServerHTTPRequest请求,要不会出现系统错误: -21466