oracle 11g中查询的响应时间过长

时间:2015-07-22 07:14:12

标签: performance oracle11g

SELECT /*+first_rows */ PPS_ID,TOTAL_WEIGHT from
                      (SELECT PPS_ID,TOTAL_WEIGHT ,row_number() over (order by total_weight desc) row_num
                        FROM (SELECT pps_id,round((((60 * name_pct_match / 100) + prs_weight + year_weight + dt_weight +
               case
                 when mother_name_pct_match = -1
               then
                 0
               else
                 (10 * mother_name_pct_match / 100)
               end)/decode(mother_name_pct_match,-1,(total_attrib_weight - mother_weight),total_attrib_weight)) * 100) total_weight
                FROM (SELECT pps_id,
                       round(func_compare_name('MUHAMMAD YASIN MUHAMMAD ASHRAF',upper(name_en),' ',60)) name_pct_match,
                       decode(prs_nationality_id, 271, 15, 0) prs_weight,
                       case
                         when upper(mother_name_en) in ('MR','MRS','MISS','NISA','M','X')
                           then -1
                         else
                           round(func_compare_name(upper('.'), upper(mother_name_en), ' ',60))
                      end mother_name_pct_match, 10 mother_weight,
                       100 total_attrib_weight,
                case when to_number(to_char(birth_date, 'yyyy')) = 2007 then 5 else 0 end year_weight,
                case when to_char(to_date('01/01/2007','DD-MM-RRRR'), 'dd') = to_char(birth_date, 'dd')
                  and to_char(to_date('01/01/07','DD-MM-RRRR'), 'mm') = to_char(birth_date, 'mm') then 10
                     when to_date('01/01/2007','DD-MM-RRRR') between birth_date-6 and birth_date+6 then 8
                     when to_date('01/01/2007','DD-MM-RRRR') between birth_date-28 and birth_date+28 then 5
                     when to_date('01/01/2007','DD-MM-RRRR') between birth_date-90 and birth_date+90 then 3
                else 0
                end dt_weight
                  FROM INDIV_PROF_sub_test123
                 WHERE birth_date = '01/01/2007'
                  AND IS_ACTIVE = 1
                  AND gender_id = 1 
                   AND round(func_compare_name('MUHAMMAD YASIN MUHAMMAD ASHRAF',upper(name_en),' ',60)) > 20
                   )
                   )
                  WHERE TOTAL_WEIGHT >= 70
                  )
                  where row_num <= 10


CREATE OR REPLACE FUNCTION VISION_APP.func_compare_name(p_name_str     IN VARCHAR2,
                                             p_str          IN VARCHAR2,
                                             p_delim        IN VARCHAR2,
                                             p_relev_thresh IN NUMBER)
  RETURN NUMBER DETERMINISTIC AS
  l_str LONG;
  l_n   NUMBER;
  TYPE mytabletype IS TABLE OF VARCHAR2(255);
  l_name_data        mytabletype := mytabletype();
  l_data             mytabletype := mytabletype();
  v_name_cnt         NUMBER := 0;
  v_pct_per_name     NUMBER := 0;
  v_pct_match        NUMBER := 0;
  v_flag             NUMBER;
  v_jaro_pct         NUMBER := 0;
  v_highest_jaro_pct NUMBER := 0;
  v_match_exact      NUMBER := 0;
  v_match_exact_res  NUMBER := 0;



BEGIN
  l_str := p_name_str || p_delim;
  LOOP
    l_n := instr(l_str, p_delim);
    EXIT WHEN(nvl(l_n, 0) = 0);

    -- condition to check if only space
    IF l_n <> 1 THEN
      l_name_data.extend;

      l_name_data(l_name_data.count) := ltrim(rtrim(substr(l_str,
                                                           1,
                                                           l_n - 1)));
      v_name_cnt := v_name_cnt + 1;
    END IF;
    l_str := substr(l_str, l_n + length(p_delim));

  END LOOP;
  v_pct_per_name := 100 / v_name_cnt;
  l_str          := p_str || p_delim;

  LOOP
    l_n := instr(l_str, p_delim);

    EXIT WHEN(nvl(l_n, 0) = 0);
    l_data.extend;
    l_data(l_data.count) := ltrim(rtrim(substr(l_str, 1, l_n - 1)));

    l_str := substr(l_str, l_n + length(p_delim));

  END LOOP;
  FOR nme IN 1 .. l_name_data.count LOOP
    v_flag             := 0;
    v_highest_jaro_pct := 0;
    FOR i IN 1 .. l_data.count LOOP
      v_jaro_pct := utl_match.jaro_winkler_similarity(l_name_data(nme),
                                                      l_data(i));

      IF soundex(l_name_data(nme)) = soundex(l_data(i)) AND
         v_jaro_pct >= p_relev_thresh THEN

        IF v_jaro_pct > v_highest_jaro_pct THEN
          v_highest_jaro_pct := v_jaro_pct;

        END IF;
      END IF;
    END LOOP;

    v_pct_match := v_pct_match +
                   (v_pct_per_name * v_highest_jaro_pct / 100);

  END LOOP;


  SELECT utl_match.edit_distance_similarity(p_name_str, p_str)
    INTO v_match_exact
    FROM dual;


    if (trunc(v_match_exact) =100  )  then
    return trunc(v_pct_match, 2);
else

if( v_match_exact   <> 0) then
  v_match_exact_res := (5 / v_match_exact) * 100;

  v_pct_match       := v_pct_match - v_match_exact_res;
   end if;

if v_pct_match  >20 then

  RETURN trunc(v_pct_match, 2);

  end if;
end if;
END;

此查询从INDIV_PROF_sub_test123表中获取结果,该表具有3500万的数据并已分区。
我在查询func_compare_name中找到了有问题的区域,我们正在使用它具有名称相似性检查功能
添加解释计划:

Plan
SELECT STATEMENT HINT: FIRST_ROWS
Cost: 262 
Bytes: 4,056 
Cardinality: 104 4 
VIEW VC_CLONE. 
Cost: 262 
Bytes: 4,056 
Cardinality: 104 3 
WINDOW SORT PUSHED RANK 
Cost: 262 
Bytes: 5,512 
Cardinality: 104 2
TABLE ACCESS BY GLOBAL INDEX ROWID TABLE VC_CLONE.INDIV_PROF_ONE_MONTH_1 
Cost: 261 
Bytes: 5,512 
Cardinality: 104 
Partition #: 3 
Partitions accessed #1672 1 
INDEX RANGE SCAN INDEX VC_CLONE.IDX_BIRTH_DT_INVID 
Cost: 4 
Cardinality: 1 – 

0 个答案:

没有答案