2013-07-31 40 views
1

我有以下簡單的動態選擇查詢甲骨文簡單的SELECT查詢優化

Select RELATIONSHIP 
    from DIME_MASTER 
WHERE CIN=? AND SSN=? AND ACCOUNT_NUMBER=? 

表有1083701條記錄。這個查詢需要11到12秒執行,這很昂貴。 DIME_MASTER表具有ACCOUNT,CARD_NUMBER INDEXES。請幫助我優化此查詢,以便查詢執行時間小於秒。

+0

好放單指數'cin','ssn'和'account_number'的所有3個選擇性的順序(列中具有最獨特值的那個應該是第一個)。如果可能的話,使索引唯一...然後動態是可怕的...我假設你的意思是你改變變量而不是每次構建查詢。 – Ben

+1

那麼,如果沒有適當的索引,難怪這是緩慢的......你嘗試了什麼?執行計劃顯示什麼? – ppeterka

+1

**您需要向我們展示表格和索引定義**以及每個表格的行數。也許你的表格定義不好。也許索引沒有正確創建。也許你沒有一個你認爲你做過的那個專欄的索引。沒有看到表和索引定義,我們不能說。我們還需要行計數,因爲這會大大影響查詢優化。如果你知道如何做一個'EXPLAIN'或者得到一個執行計劃,那就把結果也放在問題中。 –

回答

1

看看該謂語信息:

-------------------------------------- 
1 - filter(TO_NUMBER("DIME_MASTER"."SSN")=226550956 
      AND TO_NUMBER("DIME_MASTER"."ACCOUNT_NUMBER")=4425050005218650 
      AND TO_NUMBER("DIME_MASTER"."CIN")=00335093464) 

類型的列是NVARCHAR,但在查詢參數是數字。
Oracle必須將數字轉換爲字符串,但在投射時它有時不太聰明。
神諭和算命者並不總是對的;)

這些轉換可以防止查詢使用索引。

Select RELATIONSHIP 
    from DIME_MASTER 
WHERE CIN=to_char(?) AND SSN=to_char(?) AND ACCOUNT_NUMBER=to_char(?) 

然後運行這個命令::

使用顯式轉換成重寫查詢

exec dbms_stats.gather_table_stats(user, 'DIME_MASTER'); 

和運行查詢,並顯示了我們一個新的解釋計劃。

請您不要在這裏貼解釋計劃,他們是不可讀的,
請改用pastebin,並且只粘貼鏈接到這裏,謝謝。

看看這個簡單的例子,它說明了爲什麼你需要顯式轉換:

CREATE TABLE "DIME_MASTER" ( 
    "ACCOUNT_NUMBER" NVARCHAR2(16) 
); 
insert into dime_master 
select round(dbms_random.value(1, 100000)) from dual 
connect by level <= 100000; 
commit; 
create index dime_master_acc_ix on dime_master(account_number); 

explain plan for select * from dime_master 
where account_number = 123; 

select * from table(dbms_xplan.display); 

Plan hash value: 1551952897 

--------------------------------------------------------------------------------- 
| Id | Operation   | Name  | Rows | Bytes | Cost (%CPU)| Time  | 
--------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |    |  3 | 54 | 70 (3)| 00:00:01 | 
|* 1 | TABLE ACCESS FULL| DIME_MASTER |  3 | 54 | 70 (3)| 00:00:01 | 
--------------------------------------------------------------------------------- 

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

    1 - filter(TO_NUMBER("ACCOUNT_NUMBER")=123) 




explain plan for select * from dime_master 
where account_number = to_char(123); 

select * from table(dbms_xplan.display); 
Plan hash value: 3367829596 

--------------------------------------------------------------------------------------- 
| Id | Operation  | Name    | Rows | Bytes | Cost (%CPU)| Time  | 
--------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |     |  3 | 54 |  1 (0)| 00:00:01 | 
|* 1 | INDEX RANGE SCAN| DIME_MASTER_ACC_IX |  3 | 54 |  1 (0)| 00:00:01 | 
--------------------------------------------------------------------------------------- 

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

    1 - access("ACCOUNT_NUMBER"=U'123') 
+0

抱歉遲到的答覆,在看到您的答覆之前,我能夠發現它與oracle做to_char編號相同的東西,因此沒有使用必需的索引並花費更多的時間來執行查詢。我修改了我的查詢,如下所示: – user2639553

+0

從DIME_MASTER中選擇RELATIONSHIP WHERE CIN =? AND SSN =? AND ACCOUNT_NUMBER =?和CIN如'?%'和SSN如'?%'和ACCOUNT_NUMBER LIKE'?%',它開始使用索引和查詢很快。 – user2639553

0

根據列的基數(總行數/唯一值) - 您可以在每列上創建位圖索引。對於and/or操作,位圖索引非常有用。

經驗法則表明,位圖索引對於基數超過10%是有用的。

create bitmap index DIME_MASTER_CIN_BIX on DIME_MASTER (CIN); 
+0

如何在查詢中使用它? – user2639553

+0

我在DIME_MASTER(CIN)上爲CIN&SSN創建了2個位圖索引'創建位圖索引DIME_MASTER_CIN_BIX; 在DIME_MASTER(SSN)上創建位圖索引DIME_MASTER_SSN_BIX;'但性能沒有改進。查詢仍然需要11.3到11.5秒。 – user2639553

+0

DIME_MASTER結構'CREATE TABLE 「DIME」。 「DIME_MASTER」 ( 「ACCOUNT_NUMBER」 NVARCHAR2(16), 「APPLICATION_NUMBER」 NVARCHAR2(14), 「FIRST_NAME」 NVARCHAR2(15), 「LAST_NAME」 NVARCHAR2(25 ), 「SSN」 NVARCHAR2(9), 「CIN」 NVARCHAR2(12), 「日期date_updated」 DATE, 「BOOK_INDICATOR」 NVARCHAR2(1), 「CARD_NUMBER」 NVARCHAR2(16), 「關係」 NVARCHAR2( 1) )' – user2639553