2015-10-14 34 views
0

我們有一個表,它將用戶信息存儲在屬性名稱和值對中。在這張表上,我們創建了一個視圖,通過使用解碼將行轉換爲列。 MAX(DECODE(attribute_name,'FirstName',attribute_Value)) FirstName在最大解碼功能上創建索引

CREATE OR REPLACE FORCE VIEW vw_get_userinfo 
("USER_ID", "FIRSTNAME", "LASTNAME", "USEREMAIL", 
    "STREET", "CITY", "STATE", "ZIPCODE", "COUNTRY") 
AS 
    SELECT 
    t.user_id, 
    t.firstname, 
    t.lastname, 
    t.useremail, 
    t.street, 
    t.city, 
    t.state, 
    t.country 
    FROM (WITH 
      tempattributes AS (SELECT 
           user_id, 
           attribute_name, 
           attribute_value 
          FROM user_details) 
     SELECT 
      user_id, 
      MAX(DECODE(attribute_name, 'FirstName', attribute_value)) FirstName, 
      MAX(DECODE(attribute_name, 'LastName', attribute_value)) LastName, 
      MAX(DECODE(attribute_name, 'UserEmail', attribute_value)) UserEmail, 
      MAX(DECODE(attribute_name, 'Street', attribute_value)) Street, 
      MAX(DECODE(attribute_name, 'City', attribute_value))  City, 
      MAX(DECODE(attribute_name, 'State', attribute_value))  State, 
      MAX(DECODE(attribute_name, 'ZipCode', attribute_value)) Zipcode, 
      MAX(DECODE(attribute_name, 'Country', attribute_value)) Country 
     FROM tempattributes 
     GROUP BY user_id 
     ) t 

在解釋計劃,與第一名稱字段查詢時執行完整掃描。在這種情況下,基於函數的索引不適用,因爲索引不適用於按功能分組。有沒有什麼辦法可以在FirstName屬性上創建索引?

任何幫助,將不勝感激。

+1

如果您需要性能建議,則應顯示整個查詢。 –

+0

謝謝@GordonLinoff。我已經包含了查詢。 –

+0

我在查詢中看不到任何過濾器謂詞。您正在投影表中的所有行。很顯然,一個「全表掃描」是必需的。當根據「列」過濾數據時,在該列上創建一個「索引」是有意義的。如果您基於'expression'篩選數據,則需要在該列上創建「基於函數的索引」。您不需要用於投影行的索引。發佈**解釋計劃**。請參閱[如何創建和顯示EXPLAIN PLAN](http://lalitkumarb.com/2014/05/31/oracle-explain-plan/) –

回答

0

「有沒有什麼辦法可以在FirstName屬性上創建索引?」

編號索引建立在表格列上。您的視圖下的表格具有(鍵,值)對的通用結構。這種方法對於應用程序開發人員來說似乎是靈活且省時的,但是價格是由用戶以糟糕的表現來支付的。

當然,你最終還是要定義一組固定的屬性,只有結構是在視圖而不是表格中表達的。那麼你真的獲得了什麼樣的靈活性?

如果您不想定義一組固定的屬性,無論出於何種原因,您應該在12c中選擇支持的方法,如XML或JSON。至少他們的屬性是可索引的。 Find out more.

0

這可能不會幫助提高性能,但你可以編寫查詢爲:

SELECT user_id, 
     MAX(DECODE(attribute_name,'FirstName',attribute_Value)) as FirstName, 
     MAX(DECODE(attribute_name,'LastName',attribute_Value)) as LastName, 
     MAX(DECODE(attribute_name,'UserEmail',attribute_Value)) as UserEmail, 
     MAX(DECODE(attribute_name,'Street',attribute_Value)) as Street, 
     MAX(DECODE(attribute_name,'City',attribute_Value)) as City, 
     MAX(DECODE(attribute_name,'State',attribute_Value)) as State, 
     MAX(DECODE(attribute_name,'ZipCode',attribute_Value)) as ZipCode, 
     MAX(DECODE(attribute_name,'Country',attribute_Value)) as Country 
FROM user_details 
GROUP BY user_id; 

(注:我更喜歡CASEDECODE(),但我要離開你原來的邏輯)

Oracle有一個很好的優化器,但嵌套的with可能會影響它,所以這可能會更好。您也可以嘗試使用user_details(user_id, attribute_name, attribute_value)上的索引來查看是否可以提高性能。