【发布时间】:2014-03-21 12:28:27
【问题描述】:
我正在评估各种选项,以针对 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(没有上例中那么大)。
- 系统的每个用户都有自己的临时数据集(总共 100 万用户,10k 并发用户)。
- 建立数据集后,应针对它运行大约 10-50 个分析查询。
- 这些分析必须在线运行,即不能推迟到批处理作业。
问题
根据我的直觉,临时表查询“应该”比较慢,因为它(可能)涉及 I/O 和磁盘访问,而 PL/SQL 集合查询仅仅是内存中的解决方案.但在我的简单基准测试中,情况并非如此,因为临时表查询比 PL/SQL 集合查询高出 3 倍。为什么会这样?是否发生了一些 PL/SQL SQL 上下文切换?
对于定义明确的临时数据集,我是否还有其他选项可以快速(但广泛)“内存中”数据分析?是否有任何重要的公开基准比较各种选项?
【问题讨论】:
-
对我来说,更大的问题是你想用这个临时数据做什么?填充临时表或集合的速度与 imo 无关。例如,根据您要完成的任务,在 mat 视图上进行 COMPLETE 刷新可能是最佳选择。
-
@tbone:我已经更新了这个问题。我不喜欢使用物化视图的原因是: 1. 数据源是从许多经常更新的表中连接起来的。 2. 每个用户只能看到“他们的” 数据。我觉得这对于物化视图可能有点过于复杂,而不是全局临时表(它本身是基于会话的)
-
执行计划中的时间只是 Oracle 优化器的估计。真正的执行时间是多少?
-
Lukas,提醒一句:如果您使用 GTT 和连接池,请小心,您似乎认为 GTT 是一种优势,因为“每个用户应该只看到他们的数据”,而 GTT 是“本身基于会话”。根据您的应用程序和池的设置方式,您可能有不同的用户共享同一个会话。只是需要考虑的事情
-
@tbone:好点!这实际上可能是以前生产性“基准”的问题。我不认为我们当时使用过
ON COMMIT DELETE ROWS,不过......