用于计算汉明距离的索引访问

时间:2016-06-28 16:00:30

标签: oracle indexing plsql oracle11g query-performance

我在数据库列中有一个填充了字符串的表。我使用绑定变量计算列的汉明距离,然后使用单独的语句输出所有字符串值,例如汉明距离小于或等于3.

由于字符串值是绑定的,我无法在期望的结果上使用虚拟列,因为据我所知,这需要函数具有静态参数。另外,我不能使用基于函数的索引,因为我的输出是派生列。

是否有其他解决方案来优化查询而不执行全表扫描?目前扫描需要5-7秒,我想将其减少到300毫秒。谢谢。

以下是一些源代码:

CREATE OR REPLACE FUNCTION HAMMING_DIS(string1 IN varchar2, string2 IN varchar2)
RETURN number IS
distance number := 0;
BEGIN
   FOR counter IN 1..length(string1) LOOP
      IF substr(string1, counter, 1) = substr(string2, counter, 1) THEN
        distance:= distance + 1;
      END IF;
   END LOOP;
RETURN distance;
END;

SELECT * FROM
(SELECT FULL_NM AS FULL_NAME, HAMMING_DIS(FIRST_NM,'&A') AS HAMMING_DISTANCE 
 FROM STRINGS_OF_NAMES
 )
WHERE HAMMING_DISTANCE > 3;

1 个答案:

答案 0 :(得分:1)

感谢您的澄清......我将删除其他答案。

如果......这些都很重要......

  • A)你总是想找到汉明距离<1的字符串。 3(例如,有时不<3,其他时间<5)和
  • B)您的表 static 足以允许使用BITMAP索引,

然后你可以利用这样一个事实:你的查询的任何答案都必须在前4个字符中至少有2个匹配。

所以,

CREATE TABLE matt1 ( id number, str varchar(30) );

INSERT INTO matt1 SELECT rownum, dbms_random.string('U', dbms_random.value(1,30)) from dual connect by rownum <= 10000;

CREATE BITMAP INDEX i1 ON matt1 ( substr(rpad(str,4,' '),1,1) );
CREATE BITMAP INDEX i2 ON matt1 ( substr(rpad(str,4,' '),2,1) );
CREATE BITMAP INDEX i3 ON matt1 ( substr(rpad(str,4,' '),3,1) );
CREATE BITMAP INDEX i4 ON matt1 ( substr(rpad(str,4,' '),4,1) );


SELECT m.*, hamming_dis(str,:input) FROM matt1 m WHERE 
(
(substr(rpad(str,4,' '),1,1) = substr(rpad(:input,4,' '),1,1) AND 
substr(rpad(str,4,' '),2,1) = substr(rpad(:input,4,' '),2,1))
OR
(substr(rpad(str,4,' '),1,1) = substr(rpad(:input,4,' '),1,1) AND 
substr(rpad(str,4,' '),3,1) = substr(rpad(:input,4,' '),3,1))
OR
(substr(rpad(str,4,' '),1,1) = substr(rpad(:input,4,' '),1,1) AND 
substr(rpad(str,4,' '),4,1) = substr(rpad(:input,4,' '),4,1))
OR
(substr(rpad(str,4,' '),2,1) = substr(rpad(:input,4,' '),2,1) AND 
substr(rpad(str,4,' '),3,1) = substr(rpad(:input,4,' '),3,1))
OR
(substr(rpad(str,4,' '),2,1) = substr(rpad(:input,4,' '),2,1) AND 
substr(rpad(str,4,' '),4,1) = substr(rpad(:input,4,' '),4,1))
OR
(substr(rpad(str,4,' '),3,1) = substr(rpad(:input,4,' '),3,1) AND 
substr(rpad(str,4,' '),4,1) = substr(rpad(:input,4,' '),4,1))
)
AND hamming_dis(str,:input) <= 3;

您应该会看到包含大量BITMAP ORBITMAP AND操作的执行计划。

这可能会更快,因为您将限制您实际需要计算确切汉明距离的行数。

注意:我看到你想要&lt; = 3,而不是&lt; 3。这种方法应该可以扩展到一定程度。