我们有一个永远运行的简单查询。我可以说超过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
答案 0 :(得分:0)
如前所述,尝试正确索引表格。 我想的是分区表http://docs.oracle.com/cd/B10501_01/server.920/a96524/c12parti.htm
通过F.DM_CUSTOMER_DKEY或P.PRODUCT_YEAR或两者进行分区。 或者至少你可以将where语句放在product_year左右缩小并运行多个查询
答案 1 :(得分:0)
我假设表DM_PRODUCT_HIERARCHY小到足以在查询执行时适合内存。在这种情况下,最好使用散列连接,并且不需要索引。您可以尝试使用NO_INDEX提示和USE_HASH提示。
您可以将结果按非常大的事实表的DM_CUSTOMER_DKEY分组。 通过此属性对事实表进行分区很可能会显着提高性能。
您还应考虑创建聚合事实表。这可以是ETL过程的一部分。也许物化视图可行。但是我对大型物化视图的经验非常糟糕。特别是如果源表中有很多变化,您将遇到底层技术的限制。
要了解“最佳”运行时,您应该在事实表上测量全表扫描的时间。确保计算一个没有索引的列(COLUMN_X),否则您将测量扫描索引而不是表的时间。
SELECT count(COLUMN_X) from DM_CUST_RENEWAL_ADV_FACT;