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

Posted

技术标签:

【中文标题】Oracle Text 为类似 Google 的搜索栏优化查询【英文标题】:Oracle Text optimize query for a Google like search bar 【发布时间】:2020-03-10 18:25:14 【问题描述】:

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

基本上,我需要开发一个类似 Google 或 Amazon 的搜索栏,它会按名称向最终用户推荐产品。

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

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

CREATE TABLE inventory (
   text VARCHAR2(200)
);

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

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

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,在这种情况下我应该使用统计信息吗?

【问题讨论】:

听起来你觉得SQL搜索本身很快。也许问题出在其他地方。打开与数据库的连接可能只是花时间吗?您可以在代码中添加一些简单的日志记录,以确定时间是否实际在搜索中。此外,您是否会因为每次按键而同时执行多个搜索?如果是这样,那么您需要确定何时搜索和取消正在运行的搜索。 Reactive Extensions 可能有点矫枉过正,但它们的主要示例之一就是您尝试实现的搜索框。 您需要从用户单击搜索栏开始分析您的代码,并且您的应用程序完成处理返回的数据。毕竟你要返回 220,000 行。还要确保此分析包括数据传输时间。那里有瓶颈吗。这段时间被占用的地方将直接影响您的更正。如前所述,似乎 DB 部分(搜索)足够快。 @ajz 我在 Oracle 表单中使用它,所以虽然我是初学者,但我认为连接部分不是问题,可能是多个请求。 好吧,如果统计数据是陈旧的,那么更新它们不会有什么坏处,就像 first_rows 一样。但是您自己承认“使用 SQL 开发人员或 SQL*Plus 时搜索速度非常快,但通过搜索栏完成搜索时速度要慢得多”让我相信 SQL 不是问题.. 【参考方案1】:

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

我通过等待用户输入至少两个字符来解决它,然后我使用了性能更好的 fuzzy 运算符而不是通配符。

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

【讨论】:

以上是关于Oracle Text 为类似 Google 的搜索栏优化查询的主要内容,如果未能解决你的问题,请参考以下文章

TEXT() 等效于 Google 表格中的字符串?

网站运营文章LIST

text Google电子表格转换为JSON

Sublime Text3 插件收录

oracle笔记--查询10条之后记录的数据

github的搜素小技巧