Sql 为什么这个SELECT语句需要两个多小时?

Sql 为什么这个SELECT语句需要两个多小时?,sql,oracle,performance,oracle11g,query-optimization,Sql,Oracle,Performance,Oracle11g,Query Optimization,我有两个表A和B。A有6760636条记录,B有452175960条记录。下面是我正在使用的SELECT语句: SELECT /*+ parallel (T,1) */ T.* FROM TABLE_A T, TABLE_B P WHERE T.DESTINATION = P.DESTINATION AND T.SAIL_DATE = P.SAIL_DATE AND T

我有两个表A和B。A有6760636条记录,B有452175960条记录。下面是我正在使用的SELECT语句:

SELECT  /*+ parallel (T,1) */
         T.*
     FROM     TABLE_A T,
              TABLE_B P 
    WHERE     T.DESTINATION = P.DESTINATION 
          AND T.SAIL_DATE = P.SAIL_DATE 
          AND T.PACKAGE_TYPE = P.PACKAGE_TYPE 
          AND T.CABIN_CATEGORY = P.CABIN_CATEGORY 
          AND T.BOOKING_SOURCE = P.BOOKING_SOURCE 
          AND T.FARE_TYPE = P.FARE_TYPE 
          AND T.POST_DATE = P.POST_DATE;
我尝试在表_A上创建索引,但它仍然没有考虑索引并进行完整的表扫描

上面的解释计划是

| Id  | Operation                    | Name                      | Rows  | Bytes | Cost (%CPU)|    TQ  |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                           |  6760K|  1805M|   747K  (1)|        |      |            |
|   1 |  SORT AGGREGATE              |                           |     1 |    48 |            |        |      |            |
|   2 |   TABLE ACCESS BY INDEX ROWID| CL_PRICING_CONTROLS       |     1 |    48 |     2   (0)|        |      |            |
|   3 |    INDEX RANGE SCAN          | CL_PRICING_CONTROLS_IX3   |     1 |       |     1   (0)|        |      |            |
|   4 |  PX COORDINATOR              |                           |       |       |            |        |      |            |
|   5 |   PX SEND QC (RANDOM)        | :TQ10002                  |  6760K|  1805M|   747K  (1)|  Q1,02 | P->S | QC (RAND)  |
|   6 |    HASH JOIN                 |                           |  6760K|  1805M|   747K  (1)|  Q1,02 | PCWP |            |
|   7 |     PX RECEIVE               |                           |  6760K|  1437M|  1443   (1)|  Q1,02 | PCWP |            |
|   8 |      PX SEND HASH            | :TQ10001                  |  6760K|  1437M|  1443   (1)|  Q1,01 | P->P | HASH       |
|   9 |       PX BLOCK ITERATOR      |                           |  6760K|  1437M|  1443   (1)|  Q1,01 | PCWC |            |
|  10 |        TABLE ACCESS FULL     | TMP_RES_PRICE_CONTROL_111 |  6760K|  1437M|  1443   (1)|  Q1,01 | PCWP |            |
|  11 |     BUFFER SORT              |                           |       |       |            |  Q1,02 | PCWC |            |
|  12 |      PX RECEIVE              |                           |   450M|    23G|   746K  (1)|  Q1,02 | PCWP |            |
|  13 |       PX SEND HASH           | :TQ10000                  |   450M|    23G|   746K  (1)|        | S->P | HASH       |
|  14 |        INDEX FULL SCAN       | CL_PRICING_CONTROLS_IX1   |   450M|    23G|   746K  (1)|        |      |            |
我在两个表上尝试了并行查询,如下所示

SELECT  /*+ PARALLEL(T, 32)  PARALLEL(P, 32)*/
         T.*
     FROM     TABLE_A T,
              TABLE_B P 
    WHERE     T.DESTINATION = P.DESTINATION 
          AND T.SAIL_DATE = P.SAIL_DATE 
          AND T.PACKAGE_TYPE = P.PACKAGE_TYPE 
          AND T.CABIN_CATEGORY = P.CABIN_CATEGORY 
          AND T.BOOKING_SOURCE = P.BOOKING_SOURCE 
          AND T.FARE_TYPE = P.FARE_TYPE 
          AND T.POST_DATE = P.POST_DATE;
但这导致了下面的解释计划,我看到CPU的成本较低,但仍然需要两个小时

| Id  | Operation                    | Name                      | Rows  | Bytes | Cost (%CPU)|    TQ  |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                           |  6760K|  1805M| 59345   (1)|        |      |            |
|   1 |  SORT AGGREGATE              |                           |     1 |    48 |            |        |      |            |
|   2 |   TABLE ACCESS BY INDEX ROWID| CL_PRICING_CONTROLS       |     1 |    48 |     2   (0)|        |      |            |
|   3 |    INDEX RANGE SCAN          | CL_PRICING_CONTROLS_IX3   |     1 |       |     1   (0)|        |      |            |
|   4 |  PX COORDINATOR              |                           |       |       |            |        |      |            |
|   5 |   PX SEND QC (RANDOM)        | :TQ10002                  |  6760K|  1805M| 59345   (1)|  Q1,02 | P->S | QC (RAND)  |
|   6 |    HASH JOIN BUFFERED        |                           |  6760K|  1805M| 59345   (1)|  Q1,02 | PCWP |            |
|   7 |     PX RECEIVE               |                           |  6760K|  1437M|  1443   (1)|  Q1,02 | PCWP |            |
|   8 |      PX SEND HASH            | :TQ10000                  |  6760K|  1437M|  1443   (1)|  Q1,00 | P->P | HASH       |
|   9 |       PX BLOCK ITERATOR      |                           |  6760K|  1437M|  1443   (1)|  Q1,00 | PCWC |            |
|  10 |        TABLE ACCESS FULL     | TMP_RES_PRICE_CONTROL_111 |  6760K|  1437M|  1443   (1)|  Q1,00 | PCWP |            |
|  11 |     PX RECEIVE               |                           |   450M|    23G| 57858   (1)|  Q1,02 | PCWP |            |
|  12 |      PX SEND HASH            | :TQ10001                  |   450M|    23G| 57858   (1)|  Q1,01 | P->P | HASH       |
|  13 |       PX BLOCK ITERATOR      |                           |   450M|    23G| 57858   (1)|  Q1,01 | PCWC |            |
|  14 |        TABLE ACCESS FULL     | CL_PRICING_CONTROLS       |   450M|    23G| 57858   (1)|  Q1,01 | PCWP |            |

请查看您的查询,特别是其中的WHERE子句。它完全由连接条件组成。可以使用ANSI-92语法将其改写为:

SELECT  /*+ parallel (T,1) */
         T.*
FROM     TABLE_A T
          inner join TABLE_B P 
on     T.DESTINATION = P.DESTINATION 
      AND T.SAIL_DATE = P.SAIL_DATE 
      AND T.PACKAGE_TYPE = P.PACKAGE_TYPE 
      AND T.CABIN_CATEGORY = P.CABIN_CATEGORY 
      AND T.BOOKING_SOURCE = P.BOOKING_SOURCE 
      AND T.FARE_TYPE = P.FARE_TYPE 
      AND T.POST_DATE = P.POST_DATE;
因此,必须考虑每个表中的每一行。显然,全表扫描是唯一可行的访问路径

在JOIN子句中的所有列上构建复合索引不太可能改变这一点。您正在选择表_A中的所有列,因此数据库仍需要访问该表

除非两个表之间的交集中的记录数量非常少,否则在多块读取中读取表将比使用表行查找进行索引扫描更有效。事实上,在一个5亿行的表中,几乎每六行选择一行。一个索引如何使其更快



顺便问一下,您是如何决定并行度的?您的服务器有多少个CPU?还有哪些进程同时运行?最大并行服务器的价值是什么

你的问题是什么?当你问你的问题时,在文本区域右侧有一个大的橙色“如何设置格式”框,其中包含有用的信息。还有一个完整的格式化工具条。还有一个[?]按钮提供格式化帮助。还有一个预览区,位于文本区和“发布你的问题”按钮之间(这样你就必须扫描过去才能找到按钮),显示你的帖子发布时的样子。让你的帖子清晰明了,并证明你花了时间这样做,可以提高你获得好答案的机会。这些是
表格
还是
视图
?尝试在表1(目的地、航行日期、包裹类型、客舱类别、预订来源、票价类型、邮寄日期)上创建综合索引在这两个表上,都有一个可能返回数十亿行的查询。对于这样一个查询,几个小时并不是一个过多的时间。我已经为表A添加了索引,并尝试了相同的方法,当观察到解释计划时,我可以看到索引没有被使用,我还为表A做了DBMS_STATS.GATHER_TABLE_STATS。但是除了@APC answer之外没有任何用处:解释计划估计查询将返回600万行。您只是在sqlplus中将这些行假脱机到屏幕上吗?如果是这样的话,这可能会主宰你的运行时间!否则,您将如何处理这些行。