0

我们有一个永远运行的简单查询。我可以说10多个小时。事实表有超过 170 亿行。关于提高以下查询性能的任何建议或最佳实践?

SELECT
  /*+ parallel(f 4) */
  F.DM_CUSTOMER_DKEY,
  P.PRODUCT_YEAR,
  SUM(F.ADVG_COST_ACTUALS) advg_cost_actuals
FROM DM_CUST_RENEWAL_ADV_FACT F
INNER JOIN DM_PRODUCT_HIERARCHY p
ON F.DM_PRODUCT_HKEY = P.DM_PRODUCT_HKEY
GROUP BY F.DM_CUSTOMER_DKEY,
  P.PRODUCT_YEAR
ORDER BY P.PRODUCT_YEAR

这是计划

OPERATION OBJECT_NAME OPTIONS COST PARTITION_START PARTITION_STOP
SELECT STATEMENT 10931402
PX COORDINATOR
PX SEND :TQ10005 QC (ORDER) 10931402
SORT ORDER BY 10931402
PX RECEIVE 10931402
PX SEND :TQ10004 RANGE 10931402
SORT GROUP BY 10931402
PX RECEIVE 10931402
PX SEND :TQ10003 HASH 10931402
SORT GROUP BY 10931402
HASH JOIN 1964410
Access Predicates
F.DM_PRODUCT_HKEY=P.DM_PRODUCT_HKEY
PX RECEIVE 335
PX SEND :TQ10002 BROADCAST 335
VIEW index$_join$_002 335
HASH JOIN BUFFERED
Access Predicates
ROWID=ROWID
PX RECEIVE 136
PX SEND :TQ10000 HASH 136
PX
BLOCK
ITERATOR 136
INDEX DM_PRODUCT_HIERARCHY_PK FAST FULL
SCAN
136
PX RECEIVE 280
PX SEND :TQ10001 HASH 280
PX
BLOCK
ITERATOR 280
INDEX DM_PRODUCT_HIERARCHY_LPK FAST FULL
SCAN
280
PX BLOCK ITERATOR 1878718 1 369
TABLE ACCESS DM_CUST_RENEWAL_ADV_FACT FULL 1878718 1 369
4

2 回答 2

0

如前所述,尝试正确索引您的表。我想是对该表进行分区http://docs.oracle.com/cd/B10501_01/server.920/a96524/c12parti.htm

通过 F.DM_CUSTOMER_DKEY 或 P.PRODUCT_YEAR 或两者进行分区。或者至少您可以将 where 语句按 product_year 左右缩小并运行多个查询

于 2013-06-24T18:04:07.620 回答
0

我假设表 DM_PRODUCT_HIERARCHY 足够小,可以在查询执行时放入内存。在这种情况下,最好使用散列连接,并且您不需要索引。您可以尝试 NO_INDEX 提示和 USE_HASH 提示。

您按非常大的事实表的 DM_CUSTOMER_DKEY 对结果进行分组。按此属性对事实表进行分区很可能会显着提高性能。

您还应该考虑创建一个聚合事实表。这可以是 ETL 过程的一部分。也许物化视图会起作用。但是我对大型物化视图的体验非常糟糕。特别是如果源表有很多变化,你会遇到底层技术的限制。

要了解“最佳”运行时,您应该测量对事实表进行全表扫描的时间。确保计算没有索引的列(示例中的 COLUMN_X),否则您将测量扫描索引而不是表的时间。

SELECT count(COLUMN_X) from DM_CUST_RENEWAL_ADV_FACT;
于 2013-06-26T07:32:25.630 回答