2013-04-23 29 views
4

大家好:)我有兩個表,每個表大約有三千萬行,而且我正在尋求在執行計數時提高性能。在Oracle中使用JOIN優化SELECT中的計數

下面是該查詢:

SELECT count(*) 
FROM VEHICULE v 
JOIN CLIENT c ON c.CL_ID = v.VE_CL_ID 
WHERE v.VE_BRAND = 'MITSUBISHI' 
    AND c.CL_COUNTRY = 'SPAIN'; 

外鍵在VEHICULE表聲明

CONSTRAINT "VEHICULE_CLIENT_FK" FOREIGN KEY ("VE_CL_ID") 
    REFERENCES "MY_SCHEMA"."CLIENT" ("CL_ID") ENABLE 

而且有外鍵索引:

CREATE INDEX "MY_SCHEMA"."VEHICULE_INDEX_CLIENT" ON "MY_SCHEMA"."VEHICULE" ("CL_ID") 

有也是用於搜索條件的列上的索引。

請求最多可能需要40秒。我已經看過位圖連接索引,但我不知道它是否會有所幫助,因爲位圖連接應該是for columns with low cardinalities。這是連接索引的唯一類型嗎?我完全不知如何改善表現。

編輯:

下面是SQL Developer就會顯示(執行計劃)的SQL調優顧問 這個查詢的SQL是沒有AND c.CL_COUNTRY = 'SPAIN'

GENERAL INFORMATION SECTION 
------------------------------------------------------------------------------- 
Tuning Task Name : staName9168 
Tuning Task Owner : USER 
Tuning Task ID  : 12125 
Scope    : COMPREHENSIVE 
Time Limit(seconds): 1800 
Completion Status : COMPLETED 
Started at   : 04/23/2013 15:44:35 
Completed at  : 04/23/2013 15:44:36 


------------------------------------------------------------------------------- 
There are no recommendations to improve the statement. 

------------------------------------------------------------------------------- 
EXPLAIN PLANS SECTION 
------------------------------------------------------------------------------- 

1- Original 
----------- 
Plan hash value: 3808155432 

------------------------------------------------------------------------------------------------------------------------------------------ 
| Id | Operation       | Name     | Rows | Bytes | Cost (%CPU)| Time  | TQ |IN-OUT| PQ Distrib | 
------------------------------------------------------------------------------------------------------------------------------------------ 
| 0 | SELECT STATEMENT     |      |  1 | 21 | 54011 (1)| 00:10:49 |  |  |   | 
| 1 | SORT AGGREGATE      |      |  1 | 21 |   |   |  |  |   | 
| 2 | PX COORDINATOR     |      |  |  |   |   |  |  |   | 
| 3 | PX SEND QC (RANDOM)    | :TQ10001    |  1 | 21 |   |   | Q1,01 | P->S | QC (RAND) | 
| 4 |  SORT AGGREGATE     |      |  1 | 21 |   |   | Q1,01 | PCWP |   | 
|* 5 |  HASH JOIN      |      | 475K| 9745K| 54011 (1)| 00:10:49 | Q1,01 | PCWP |   | 
| 6 |  BUFFER SORT     |      |  |  |   |   | Q1,01 | PCWC |   | 
| 7 |  PX RECEIVE     |      | 475K| 6497K| 32813 (1)| 00:06:34 | Q1,01 | PCWP |   | 
| 8 |   PX SEND BROADCAST   | :TQ10000    | 475K| 6497K| 32813 (1)| 00:06:34 |  | S->P | BROADCAST | 
|* 9 |   TABLE ACCESS BY INDEX ROWID| VEHICULE    | 475K| 6497K| 32813 (1)| 00:06:34 |  |  |   | 
|* 10 |   INDEX RANGE SCAN   | VEHICULE_INDEX_BRAND | 616K|  | 1621 (2)| 00:00:20 |  |  |   | 
| 11 |  PX BLOCK ITERATOR    |      | 20M| 138M| 21146 (1)| 00:04:14 | Q1,01 | PCWC |   | 
| 12 |  TABLE ACCESS FULL   | CLIENT    | 20M| 138M| 21146 (1)| 00:04:14 | Q1,01 | PCWP |   | 
------------------------------------------------------------------------------------------------------------------------------------------ 

Query Block Name/Object Alias (identified by operation id): 
------------------------------------------------------------- 

    1 - SEL$58A6D7F6 
    9 - SEL$58A6D7F6/[email protected]$1 
    10 - SEL$58A6D7F6/[email protected]$1 
    12 - SEL$58A6D7F6/[email protected]$1 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    5 - access("VE_CL_ID"="CL_ID") 
    9 - filter("VE_CL_ID" IS NOT NULL) 
    10 - access("VEHICULE"."VE_BRAND"='MITSUBISHI') 

Column Projection Information (identified by operation id): 
----------------------------------------------------------- 

    1 - (#keys=0) COUNT()[22] 
    2 - SYS_OP_MSR()[10] 
    3 - (#keys=0) SYS_OP_MSR()[10] 
    4 - (#keys=0) SYS_OP_MSR()[10] 
    5 - (#keys=1) 
    6 - (#keys=0) "VE_CL_ID"[NUMBER,22] 
    7 - "VE_CL_ID"[NUMBER,22] 
    8 - (#keys=0) "VE_CL_ID"[NUMBER,22] 
    9 - "VE_CL_ID"[NUMBER,22] 
    10 - "VEHICULE".ROWID[ROWID,10] 
    11 - "CL_ID"[NUMBER,22] 
    12 - "CL_ID"[NUMBER,22] 

------------------------------------------------------------------------------- 
+2

執行計劃顯示什麼? 「ve_brand」或「cl_country」上是否有索引,如果有的話,它們的選擇性以及它們選擇用於每個表的索引是多少? – 2013-04-23 13:42:50

+0

你需要在你的'客戶端'表上的索引,參見。解釋計劃的編號12。 – collapsar 2013-04-23 13:56:37

+0

@AlexPoole've_brand'和'cl_country'被編入索引。我會說他們代表每個5%的列。執行計劃始終顯示搜索條件的「INDEX RANGE SCAN」。 (執行計劃包含在編輯中)。單獨的每個表上的SELECT查詢速度非常快,但連接會降低性能。 – BenoitParis 2013-04-23 13:57:15

回答

3

client (cl_country, cl_id)vehicule (ve_brand, ve_cl_id)建立複合索引(包括按此順序)。

這樣你就可以擺脫兩個表上的表訪問。

如果您只有少數國家和品牌可能,您還可以按國家和品牌對指標進行劃分,以便可以使用INDEX FAST FULL SCAN而不是INDEX RANGE SCAN

您也可以考慮在client.id上創建集羣,這樣可以使車輛和客戶端數據存儲在相同或鄰近的數據塊中,從而改善I/O。

+0

我調整了PrePROD環境(包含較少數據)和具有主鍵/外鍵的複合索引做的事情:)但我不知道PROD中的性能是否會很好。有幾種類型的分區索引,你是在想一個特定的索引嗎? – BenoitParis 2013-04-23 14:51:32

+0

@BenoitParis:不幸的是,你不能列出Oracle全局索引分區。您需要分別按列表(品牌)和列表(國家)對錶格進行分區,並創建本地分區索引。 – Quassnoi 2013-04-23 15:03:17