java - Oracle Text 优化类似 Google 搜索栏的查询

标签 java oracle plsql oracleforms oracle-text

首先,我无法提供实现代码,因为我认为它没有用,所以我会尝试详细解释到目前为止我所做的事情。

基本上,我需要开发一个类似谷歌或亚马逊的搜索栏,它将按名称向最终用户推荐产品。

搜索栏和建议面板是用纯 Java (Swing) 编写的。而数据存储在 Oracle (10g) DB 表中。由于我需要搜索 VARCHAR2 列,因此我查找了全文搜索包并找到了 Oracle Text。使用 SQL Developer 或 SQL*Plus 时搜索速度非常快,但通过搜索栏完成搜索时速度要慢得多。

该表如下所示,大约有 220k 行,在 text 列上,我为 Oracle Text 创建了基本的 CONTEXT 索引。

CREATE TABLE inventory (
   text VARCHAR2(200)
);

CREATE INDEX idx_inventory ON inventory(text) INDEXTYPE IS CTXSYS.CONTEXT;

搜索是在带有游标的数据库包中实现的,也在同一个包中我手动进行查询解析,并且运行速度也很快。由于它单独运行得非常快,我不认为问题出在包中,但我会提供一个简短的解释。

CREATE OR REPLACE PACKAGE BODY pkg_inventory 
AS
  FUNCTION f_parse_query(p_query IN VARCHAR2) RETURN VARCHAR2 
  IS
    v_query VARCHAR2(32767) := '';
  BEGIN
    -- it always returns a parsed string with the following format
    -- {foo} & {bar} & baz%
    -- all the words are escaped unless for the last one, at the end of which the "%" is added
    RETURN v_query;
  END f_parse_query;

  FUNCTION f_search(p_query IN VARCHAR2) RETURN VARCHAR2 
  IS
    CURSOR c_inventory IS 
           SELECT  text
               FROM inventory
           WHERE CONTAINS(text, v_query, 1) > 0
           ORDER BY score(1) DESC;

    v_query VARCHAR(32767);
    v_res   VARCHAR(32767);

    TYPE t_result IS TABLE OF VARCHAR(32767) INDEX BY BINARY_INTEGER;
    tab_res t_result;
  BEGIN
    v_query := f_parse_query(p_query);
    OPEN c_inventory;
    FETCH c_inventory BULK COLLECT INTO tab_res LIMIT 10;
    CLOSE c_inventory;

    -- concatenate the result in a string and return
    RETURN v_res;
  END f_search;
END pkg_inventory;

为了使搜索体验具有响应性,我在每次键入字符后都会重做整个过程,而真正的瓶颈是当我开始键入单词时,我需要等待几秒钟才能得到结果,因此解析的查询看起来像“b%”或“{bar} & f%”。

如何使搜索更快、响应更灵敏?

也许我可以等待用户输入至少三个字母后进行搜索。或者我可以使用编译器提示 /*+ FIRST_ROWS(10) */ 但这是值得的,因为我使用 BULK COLLECT 在这种情况下我应该使用统计信息吗?

最佳答案

问题出在最后一个单词后面的通配符 % 中,这导致了我所描述的性能问题。

我通过等待用户输入至少两个字符来解决这个问题,然后我使用性能更好的模糊运算符代替通配符。

老实说,我没有尝试过的另一个可能的解决方案是创建一个前缀索引来面对通配符 % 的问题,因为正如文档所述,它针对左截断搜索(即 bar%)进行了高度优化。

关于java - Oracle Text 优化类似 Google 搜索栏的查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60623768/

相关文章:

java - 将 java 控制台附加到文件

java - JNA:无法创建结构子类的对象 - 结构字段无效

oracle - SQL 表中的列数超过 50

java - 从 XML 生成 SQL 模式

c# - 如何检索 Oracle 过程或函数的主体

java - MIDI 的可行替代品?

java - 从 AST 获取方法调用信息

database - Oracle:在实时数据库中添加、重命名和删除列

oracle - 如何在 SQL PLUS 中纠正这个问题?

oracle - 如何使用 SYS_REFCURSOR 处理 NO DATA FOUND - ORACLE