【问题标题】:How to force Index usage on columns in Merge Statement in Oracle如何在 Oracle 合并语句中的列上强制使用索引
【发布时间】:2012-01-01 10:07:47
【问题描述】:

我正在开发 Oracle 10gR2

我有一个表 TBL_CUSTOMER 的 MERGE 语句。 TBL_CUSTOMER 包含一列 USERNAME,其中包含电子邮件地址。此表中存储的数据不区分大小写,如传入的数据可以是大写、小写或任意大小写组合。

在合并数据时,我必须确保在不考虑大小写的情况下比较数据。我已经创建了一个基于 USERNAME 列的函数索引作为 UPPER(USERNAME)。

MERGE INTO tbl_customer t
      USING (SELECT /*+ dynamic_sampling(a 2) */  NVL(
                                                      (x.username||decode((x.cnt+x.rn-1),0,null,(x.cnt+x.rn-1))),
                                                      t1.cust_username
                                                     ) community_id
                               ,DECODE (source_system_name,'SYS1', t1.cust_firstname,t1.cust_username) display_name
                               ,t1.cust_username
                              ,t1.cust_id cust_id
                              ,t1.cust_account_no cust_account_no
                              ,t1.cust_creation_date
                              ,t1.source_system_name
                              ,t1.seq_no
                              ,nvl(t1.cust_email,'NULLEMAIL') cust_email
                              ,t1.file_name
                              ,t1.diakey
                              ,t1.sourcetupleidcustmer
                              ,DECODE (source_system_name,'SYS1','DefaultPassword',t1.cust_password) cust_password
             FROM   gtt_customer_data t1,
                    (SELECT a.username,
                            cust_id,
                            row_number() over(partition by lower(a.username) order by  seq_no) rn,
                            (SELECT count(community_id)FROM TBL_customer where regexp_like (lower(community_id) ,'^'||lower(a.username)||'[0-9]*$'))cnt
                     FROM   gtt_cust_count_name a  
                    ) x
             WHERE  t1.cust_status = 'A'
             AND    x.cust_id(+)  = t1.cust_id
             AND    nvl(t1.op_code,'X') <> 'D'
             AND    t1.cust_id is not null
             AND    cust_email is not null
            ) a
      ON    ( 
             (a.sourcetupleidcustmer = t.source_tuple_id AND a.source_system_name =t.created_by)
             OR 
             ( upper(a.cust_email) = upper(t.username) AND a.source_system_name ='SYS2' )
            )

当我检查解释计划时,没有使用基于函数的 USERNAME 索引。我注意到如果我删除 OR 条件,则使用索引,但由于复杂的业务逻辑,我无法删除它。

如何强制使用该索引?

【问题讨论】:

  • 您的 dynamic_sampling 提示不起作用。您应该将它移到 X 内联视图内。

标签: sql oracle oracle10g indexing sql-tuning


【解决方案1】:

Oracle 允许您创建基于函数的索引,在您的情况下是 upper(username)。您也可以在查询中尝试INDEX 提示,但我认为在您的情况下,基于函数的索引是一个更好的解决方案。

如果索引字段是函数的参数,则通常不使用 BTree 索引(假设 WHERE 中的函数并且它不是覆盖索引)。例如,WHERE trunc(date_field) = trunc(sysdate()) 不会在date_field 上使用索引,但会在(trunc(date_field)) 上使用索引。

【讨论】:

  • 感谢您的建议,亚历克斯。让我尝试按照您建议的方式创建索引 - (UPPER(USERNAME))
猜你喜欢
  • 1970-01-01
  • 2016-10-15
  • 2013-06-13
  • 2021-06-19
  • 1970-01-01
  • 2016-04-21
  • 1970-01-01
  • 1970-01-01
  • 2015-04-18
相关资源
最近更新 更多