SQL查询在Oracle中执行的执行时间不同

时间:2014-03-21 06:15:03

标签: sql performance oracle oracle11g oracle10g

我有一个运行正常并给我输出的查询,问题是,同样的查询花费不同的经过时间来运行它。 avereage elapased的时间是10分钟,但有时需要花费一个多小时的时间并使用sql_profile进行查询以获得最佳的执行计划,并且DBA每次都强制它。

INSERT INTO DATA_UPDATE_EVENT
(
  structure_definition_id,
  eod_run_id,
  publish_group_name,
  JMSDBUS_DESTINATION,
  dbaxbuild_location,
  LOCATION,
   original_data_type)
  SELECT  DISTINCT eod_structure_definition_id,
   p_eod_run_id,
   p_publish_group,
   pg.JMSDBUS_DESTINATION,
   pg.dbaxbuild_location,
   pg.LOCATION,
   sd.DATA_TYPE
  FROM
   PUBLISH_GROUP pg,
   STRUCTURE_EOD_MAPPING sem,
   WATCH_LIST_STRUCTURE wls,
   STRUCTURE_DEFINITION sd
  WHERE  pg.publish_group_name = sem.publish_group_name
  AND sem.publish_group_name = p_publish_group
  AND wls.structure_definition_id = sem.structure_definition_id
  AND wls.watch_list_id IN (SELECT watch_list_id
                            FROM TMP_WATCHLIST)
  AND sd.structure_definition_id = sem.structure_definition_id
  AND (sd.defcurve_name IS NULL
                                OR sd.defcurve_name IN (SELECT curve_shortname
                                                        FROM
                                                        DEFCURVE_CURRENT
                                                        WHERE  CURVE_STATUS = 'live')
       )
   AND (sd.generic_class_name is null
   or sd.generic_class_name <> 'CREDIT' 
                        or (
                             sd.generic_class_name = 'CREDIT'
                             and generic_name in
                             (
                               select generic_name
                               from 
                               analytic_object ao,
                               analytic_object_instance aoi,
                               analytic_object_property aop,
                               defcurve_current dc
                               where ao.analytic_object_id = aoi.analytic_object_id
                               and aop.analytic_object_instance_id  =aoi.analytic_object_instance_id
                                and AOP.PROPERTY_NAME = 'CreditObjectName'
                                and aop.prop_value1 = dc.curve_shortname
                                and aop.effective_to > systimestamp
                                and aop.effective_from < systimestamp
                                and dc.curve_status = 'live'
                                and aoi.analytic_object_instance_id in
                                 (select analytic_object_instance_id
                                  from 
                                  analytic_object_property
                                  where property_name = 'CreditObjectType'
                                 )
        )
   )
); 

请采取上述查询的执行计划

Execution Plan
------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                    | Name                        | Rows  | Bytes | Cost (%CPU)| Time
------------------------------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT                             |                             |       |       |   232 (100)|
|   1 |  VIEW                                        | VW_DIS_1                    |     1 |  4052 |   232   (1)| 00:00:
|   2 |   SORT UNIQUE                                |                             |     1 |   186 |   232   (1)| 00:00:
|   3 |    FILTER                                    |                             |       |       |            |
|   4 |     NESTED LOOPS                             |                             |     1 |   186 |   231   (0)| 00:00:
|   5 |      NESTED LOOPS                            |                             |     1 |   158 |   229   (0)| 00:00:
|   6 |       NESTED LOOPS                           |                             |     1 |   132 |   228   (0)| 00:00:
|   7 |        NESTED LOOPS                          |                             |    15 |  1830 |     3   (0)| 00:00:
|   8 |         TABLE ACCESS BY INDEX ROWID          | PUBLISH_GROUP               |     1 |   109 |     1   (0)| 00:00:
|   9 |          INDEX UNIQUE SCAN                   | PK$PUBLISHGROUP             |     1 |       |     0   (0)|
|  10 |         TABLE ACCESS FULL                    | TMP_WATCHLIST               |    15 |   195 |     2   (0)| 00:00:
|  11 |        INDEX RANGE SCAN                      | PK$WATCHLISTSTRUCTURE       |  1322 | 13220 |    15   (0)| 00:00:
|  12 |       INDEX UNIQUE SCAN                      | PK$STRUCTURE_EOD_MAPPING    |     1 |    26 |     1   (0)| 00:00:
|  13 |      TABLE ACCESS BY INDEX ROWID             | STRUCTURE_DEFINITION        |     1 |    28 |     2   (0)| 00:00:
|  14 |       INDEX UNIQUE SCAN                      | PK$STRUCTURE_DEFINITION     |     1 |       |     1   (0)| 00:00:
|  15 |     TABLE ACCESS BY INDEX ROWID              | DEFCURVE_CURRENT            |     1 |    22 |     2   (0)| 00:00:
|  16 |      INDEX UNIQUE SCAN                       | PK$DEFCURVE_CURRENT         |     1 |       |     1   (0)| 00:00:
|  17 |      PX COORDINATOR                          |                             |       |       |            |
|  18 |       PX SEND QC (RANDOM)                    | :TQ10000                    |     1 |   118 |  5023   (1)| 00:01:
|  19 |        NESTED LOOPS                          |                             |     1 |   118 |  5023   (1)| 00:01:
|  20 |         NESTED LOOPS                         |                             |     1 |    96 |  5023   (1)| 00:01:
|  21 |          NESTED LOOPS                        |                             |   135 |  6480 |  4939   (1)| 00:01:
|  22 |           NESTED LOOPS                       |                             |  8343 |   236K|  1228   (1)| 00:00:
|  23 |            PX BLOCK ITERATOR                 |                             |       |       |            |
|  24 |             TABLE ACCESS FULL                | ANALYTIC_OBJECT             |    28 |   504 |   231   (1)| 00:00:
|  25 |            TABLE ACCESS BY GLOBAL INDEX ROWID| ANALYTIC_OBJECT_INSTANCE    |   300 |  3300 |   298   (0)| 00:00:
|  26 |             INDEX RANGE SCAN                 | UQ$ANALYTIC_OBJECT_INSTANCE |   300 |       |     3   (0)| 00:00:
|  27 |           INDEX UNIQUE SCAN                  | PK$ANALYTIC_OBJECT_PROPERTY |     1 |    19 |     2   (0)| 00:00:
|  28 |          TABLE ACCESS BY GLOBAL INDEX ROWID  | ANALYTIC_OBJECT_PROPERTY    |     1 |    48 |     3   (0)| 00:00:
|  29 |           INDEX UNIQUE SCAN                  | PK$ANALYTIC_OBJECT_PROPERTY |     1 |       |     2   (0)| 00:00:
|  30 |         TABLE ACCESS BY INDEX ROWID          | DEFCURVE_CURRENT            |     1 |    22 |     1   (0)| 00:00:
|  31 |          INDEX UNIQUE SCAN                   | PK$DEFCURVE_CURRENT         |     1 |       |     0   (0)|
------------------------------------------------------------------------------------------------------------------------ 

Note
-----
  - dynamic sampling used for this statement
  - SQL profile "SYS_SQLPROF_01505a8ce6144000" used for this statement

有人可以建议如何通过良好的步骤以及我们需要DBA提供信息来实现这一目标。

2 个答案:

答案 0 :(得分:1)

您或您的DBA需要了解您的数据和系统。这是调整的最基本原则。

如果环境稳定,查询将以可预测的方式执行。如果运行时间变化很大,那么您需要找到不同的东西。不正常的性能可能是由于许多其他用户在特定时间争用系统资源,或者可能是由于数据量或性质的变化。还有其他可能性,但那些是开始的。

您的DBA应该已经监控数据库使用情况。但如果他们不是,他们需要立即开始 。由于您的组织似乎不太愿意为Diagnostics option付费,因此您可以使用Statspack。 Find out more

至于数据变化,发布的代码中有一条线索:

AND wls.watch_list_id IN (SELECT watch_list_id
                            FROM TMP_WATCHLIST)

假设你坚持一个明智的命名惯例(多年来SO已经说服我对这些假设保持警惕),那么TMP_WATCHLIST就是一个临时表。这表明每次运行查询时它都可以保存不同的数据和不同的数据量。如果是这样的话,这将是一个很好的起点。根据确切的问题,可能的解决方案包括动态采样,固定统计或基数提示。

答案 1 :(得分:1)

以下是一些想法:

  1. 绑定变量? p_publish_group是绑定变量吗?如果是这样,sem.publish_group_name上是否有直方图?看起来这个查询根据输入返回了大不相同的数量。自适应游标共享可能有所帮助,但这需要直方图。
  2. 不良资料?基数估算可怕。如果这个语句运行了一个小时,那么我会假设有数百万行。但Oracle只需要1行,即使使用SQL Profile。配置文件是在非常小的数据集上创建的,并应用于更大的数据集吗?
  3. 完整提示?即使您的优化程序统计信息准确无误,我敢打赌基数仍然很遥远。这可能是那些非常奇怪的查询之一,它需要大量的提示。例如,像/*+ full(pg) full(sem) use_hash(pg sem) ... */这样的东西。索引和嵌套循环适用于少量数据。但如果此查询运行一小时,则可能需要全表扫描和散列连接。
  4. SQL监控。运行select dbms_sqltune.report_sql_monitor(sql_id => '<your sql id>', type => 'text') from dual;以查明查询实际执行的操作以及每次操作花费的时间。解释计划只是估算,您需要知道真正正在发生什么。我敢打赌,当你运行它时,你会看到一些长期运行的步骤,其中Estimated Rows = 1,Actual Rows = 1000000。