2013-04-16 67 views
1

以下是我正在使用聚合函數的查詢。 where子句很簡單,在corpId和incoming_date上有一個索引。 如果我簡單地提取所有行/計數,查詢需要的時間不到一秒鐘。但是,當我使用聚合函數查詢需要大約4分鐘。 我使用的是oracle 11i,where子句檢索的總行數在64000左右。最近還收集了表和索引統計信息,表中沒有添加新行。在使用Oracle聚合函數時查詢性能

請建議提高速度。

SELECT 
sum(paid_amt) totalamount 
FROM test_table e 
WHERE e.corpId =6 
AND e. incoming_date >= to_date('01-12-2012','dd-mm-yyyy') 
AND e. incoming _date <= to_date('09-01-2013','dd-mm-yyyy') 
+2

什麼是您正在運行的兩個查詢?特別是,當你不使用聚合函數時,你是否選擇了「paid_amt」列?兩個查詢計劃是什麼?你是否說要返回64,000行中的最後一行需要不到一秒的時間?或者,您是否使用了GUI,在獲取最後一行之前顯示前幾行? –

+0

2個查詢:第一個是我已經發布的一個,第二個是提取計數的計數(使用count(*))。計數在不到一秒的時間內達到64k,而總和需要4分鐘。 – user2194253

回答

3

包括paid_amt到索引:

CREATE INDEX 
     ix_testtable_cord_date_paid 
ON  test_table (corpId, incoming_date, paid_amt) 

如果你只是(corpId, incoming_date)有一個索引,並嘗試測試速度是這樣的:

SELECT COUNT(*) 
FROM test_table 
WHERE e.corpId = 6 
     AND e.incoming_date >= to_date('01-12-2012','dd-mm-yyyy') 
     AND e.incoming_date <= to_date('09-01-2013','dd-mm-yyyy') 

你不查詢外的任何東西索引,因此查詢可以單獨滿足INDEX (RANGE SCAN)

只要您添加不在索引中的任何東西(您的案例中爲paid_amt),查詢需要使用其他TABLE ACCESS (BY INDEX ROWID)從表中檢索記錄。

它是嵌套循環中的隨機查找,速度很慢,特別是在表記錄很大(包含大量字段或長字段)的情況下。

優化器甚至可能認爲此訪問方法的效率較低,因此FULL SCAN並使用後者。

+0

是的。謝謝。我正在創建組合索引(corpId,incoming_date,paid_amt)。該表有319,332,896條記錄。所以創建索引需要一些時間。索引創建後會發佈更新。 – user2194253

+0

感謝您的建議。它運作良好。總和需要0.1秒。如果我改變了我的查詢下面的一個: – user2194253

+0

SELECT NVL(SUM(paid_amt),0)paidAmount, NVL(SUM(cust_served),0)totalCustServed, NVL(SUM(BILLED_AMT,0))billedAmt, NVL (SUM(e.tax_paid,0))taxPaid, COUNT(DISTINCT CUST_NAME)CUSTNAME, NVL(SUM(bal_Payment,0))balPayment, NVL(SUM(adv_payment,0))advPayment FROM TEST_TABLEë WHERE 1 = 1 AND e.corp_id = 92 AND e.incoming_date> = '02 -Aug-2012' AND e.incoming__date <= '09-Jan-2013' – user2194253

0

我重新這種情況下是這樣的...

CREATE TABLE test_table 
    (id integer 
    , corpId integer 
    , paid_amt number(10,2) 
    , incoming_date DATE); 

ALTER TABLE test_table 
add CONSTRAINT test_table_pk PRIMARY KEY (id); 

create index test_table_nui_1 on test_table(corpId); 

create index test_table_nui_2 on test_table(incoming_date); 

create sequence test_table_seq; 

insert into test_table 
    select test_table_seq.nextval 
     ,MOD(test_table_seq.currval,6) 
     ,MOD(test_table_seq.currval,10) + 1 
     ,sysdate - MOD(test_table_seq.currval,200) 
    from all_objects, user_objects; 

笛卡爾ALL_OBJECTS和USER_OBJECTS之間的連接僅僅是一個黑客獲得快速插入記錄的負載。 (在這種情況下657000行)

通過選擇運行第一所有657000 ...

select sum(paid_amt) 
from test_table; 

計劃 SELECT語句ALL_ROWSCost:621字節:13基數:1個
2 SORT AGGREGATE字節:13基數:1
1個TABLE ACCESS FULL TABLE DAVE.TEST_TABLE費用:621字節:9923914基數:763378

然後109650一corpId ...

select sum(paid_amt) 
from test_table 
where corpId = 5; 

計劃 SELECT語句ALL_ROWSCost:265字節:26基數:1個
3 SORT AGGREGATE字節:26基數:1
2表訪問由INDEX ROWID表DAVE.TEST_TABLE成本:265字節:3310138基數:127313
1 INDEX RANGE掃描索引DAVE.TEST_TABLE_NUI_1費用:213基數:3,054

最後20,836行按日期限制...

SELECT sum(paid_amt) totalamount 
FROM test_table e 
WHERE e.corpId = 5 
AND e. incoming_date >= to_date('01-12-2012','dd-mm-yyyy') 
AND e. incoming_date <= to_date('09-01-2013','dd-mm-yyyy') 

計劃 SELECT語句ALL_ROWSCost:265字節:35基數:1個
3 SORT AGGREGATE字節:35基數:1
2表訪問由INDEX ROWID表DAVE.TEST_TABLE成本:265字節:871360基數:24896
1個索引範圍掃描INDEX DAVE.TEST_TABLE_NUI_1成本:213基數:3054個

所有3個查詢是快速(即< 0.5秒)

另一種方法是刪除nui_1和nui_2,並在兩列上創建組合索引。這則在31毫秒跑在我的分貝

create index test_table_nui_3 on test_table(corpId, incoming_date); 

計劃 SELECT語句ALL_ROWSCost:15字節:35基數:1級
3排序骨料字節:35基數:1
2 TABLE ACCESS BY INDEX ROWID表DAVE。 TEST_TABLE費用:15字節:871360基數:24896
1索引範圍掃描索引DAVE.TEST_TABLE_NUI_3費用:3基數:14

這表明聚合函數是沒有問題的,但你的索引可能。最好的辦法是檢查你的解釋計劃。

+0

我已經在(corpId,incoming_date)上有一個複合索引。問題是test_table本身有319,332,896條記錄。我已經指定的where子句獲取由於組合索引而快(小於一秒)的64k記錄(使用count(*))。計算這條64k記錄的總和(paid_amt)需要很長時間。 – user2194253

+0

抱歉沒有意識到桌子太大了。 – Dave

+0

你可以考慮在corp_id和/或日期分區,或者你可以使用物化視圖。即使在將行數加倍後,MV也將我的示例降低到只有15ms。 – Dave