【问题标题】:Oracle- Insert query slowOracle-插入查询慢
【发布时间】:2020-09-05 20:48:44
【问题描述】:

我正在插入:

insert /*+ NOLOGGING */ into myTable
  select /*+ parallel(3) */ * from myTmpTable;

这里是解释计划:

------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name                       | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
------------------------------------------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT         |                            |  110M |  5776M|    91428(2)| 00:03:30 |        |      |            |
|   1 |  LOAD TABLE CONVENTIONAL | myTable                    |       |       |            |          |        |      |            |
|   2 |   PX COORDINATOR         |                            |       |       |            |          |        |      |            |
|   3 |    PX SEND QC (RANDOM)   | :TQ10000                   |  110M |  5776M|    91428(2)| 00:03:30 |  Q1,00 | P->S | QC (RAND)  |
|   4 |     PX BLOCK ITERATOR    |                            |  110M |  5776M|    91428(2)| 00:03:30 |  Q1,00 | PCWC |            |
|   5 |      TABLE ACCESS FULL   | myTmpTable                 |  110M |  5776M|    91428(2)| 00:03:30 |  Q1,00 | PCWP |            |
------------------------------------------------------------------------------------------------------------------------------------

myTmpTable 总共有 110M 的行,并且 myTable 的 pk 已经设置在临时 tale 中。

当我运行在 FULL ACCES 期间看到的查询时,当达到 60M 时,性能显着下降,它在开始加载 5M 时加载 1k/500 行。

优化器


NAME                                 TYPE    VALUE    
------------------------------------ ------- -------- 
optimizer_capture_sql_plan_baselines boolean FALSE    
optimizer_dynamic_sampling           integer 2        
optimizer_features_enable            string  11.2.0.4 
optimizer_index_caching              integer 0        
optimizer_index_cost_adj             integer 100      
optimizer_mode                       string  ALL_ROWS 
optimizer_secure_view_merging        boolean TRUE     
optimizer_use_invisible_indexes      boolean FALSE    
optimizer_use_pending_statistics     boolean FALSE    
optimizer_use_sql_plan_baselines     boolean TRUE 

编辑

这里是执行部分 2M(或多或少)后的统计数据:

                        Total     For Execution   For Row
Executions                  1                 1     <0.01
Time Elapsed(sec)   22.862,82         22.862,82      0,01
Time CPU(sec)          673,69            673,69     <0.01
Buffer Requests    26.019.084        26.019.084     12,70
Disk Reads          3.073.558         3.073.558      1.50
Direct                      0                 0      0,00
Rows               2.0048.853        2.0048.853         1
FETCH                       0                 0         0

【问题讨论】:

  • 这是真正的查询:你怎么能有 97M 的行,而 EXPLAIN PLAN 只说大约 80000?你运行 DBMS_STATS 了吗? EXPLAN PLAN 说估计查询执行时间是 1 秒:实际执行时间是多少?请发布community.oracle.com/thread/865295中列出的输出。
  • 用更新的数据进行编辑,真正的执行时间是该语句从 3 小时开始运行并加载了 72M 的行。
  • 如果你从一个表中选择数据,你永远不应该进行并行查询串行插入。在非并行模式下执行正常的insert select,或启用PARALLEL_DML。另外,根据您的里程数,您很可能会在目标表上找到触发器 - 使用 APPEND 提示跳过它并比较响应时间。
  • 不幸的是我不能使用附加提示 bcs 我不能在惰性操作期间锁定 te 表,并行 dml 也是如此。
  • 1.1 亿行,您无法获得停机时间?无论谁需要这个,都必须对非常慢的插入语句感到满意。如果您的数据适合,您可以考虑“分区交换”...

标签: oracle oracle11g query-performance


【解决方案1】:

我认为NOLOGGING 是错误的。它应该转到一个 alter table 语句:

ALTER TABLE mytable NOLOGGING;

ALTER SESSION ENABLE PARALLEL DML;

提示应该是APPEND,而不是nologging:

insert /*+ APPEND */ into myTable
  select * from myTmpTable;

【讨论】:

  • 不幸的是我不能使用附加提示 bcs 我不能在惰性操作期间锁定 te 表,对于并行 dml 也是如此。
【解决方案2】:

您的 INSERT 语句非常非常非常慢,因为我已经在我的家用 PC 上使用 Linux VM 中的 Oracle 11.2.0.4 测试了类似的请求。

我有一个 9 GB 的表(1.34 亿行),我可以在 11 分钟内不进行并行复制:

OPS$ORACLE@FTEX>explain plan for insert into nt select * from t;

Explained.

OPS$ORACLE@FTEX>select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 1601196873

---------------------------------------------------------------------------------
| Id  | Operation        | Name | Rows  | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
|   0 | INSERT STATEMENT     |  |   134M|  9472M|   402K  (1)| 01:20:28 |
|   1 |  LOAD TABLE CONVENTIONAL | NT   |   |   |        |      |
|   2 |   TABLE ACCESS FULL  | T    |   134M|  9472M|   402K  (1)| 01:20:28 |
---------------------------------------------------------------------------------

9 rows selected.

OPS$ORACLE@FTEX>set timing on
OPS$ORACLE@FTEX>insert into nt select * from t;

134217728 rows created.

Elapsed: 00:11:16.40             
OPS$ORACLE@FTEX>commit;

但如果没有真正的执行计划,就不可能知道时间花在了哪里(CPU ? IO ? 其他什么???):我们只能尝试猜测和“在黑暗中射击”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多