2015-10-14 62 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)上的索引来查看是否可以提高性能。