利用PostgreSQL实现毫秒级全文检索

Lateral是一家内容推荐服务提供商,其模拟程序使用PostgreSQL存储文档。每个文档包含一个 text列和一个存储标题、日期和URL等元数据的JSON列。他们希望为模拟程序创建快速搜索功能,搜索文档全文和标题,生成推荐内容。近 日,Lateral首席技术官Max撰文介绍了他们的做法。

为了实现这一目标,可以选择开源解决方案Apache Solr或Elasticsearch,也可以选择托管解决方案Elastic或Algolia,但出于以下考虑,他们选择了PostgreSQL的全文搜索功能:

  • 不需要额外安装软件或库
  • 可以重用他们在应用程序中使用的数据库接口
  • 不需要配置额外的服务器
  • 不增加成本
  • 数据可以存储在可控的地方
  • 不需要在不同的数据源之间同步数据

虽然PostgreSQL搜索的精度和大规模查询速度存在缺陷,但Max认为,它可以满足他们的应用场景。以下是他们的做法:

  • 创建一个列tsv,存储tsvector值;
  • 在新建的列上创建索引,并用下面的语句填充列:
    UPDATE data_rows SET tsv
    =setweight(to_tsvector(coalesce(meta->>‘title‘,‘‘)), ‘A‘)
    ||setweight(to_tsvector(coalesce(text,‘‘)), ‘D‘);

    此处需要注意,JSON列的权重为A,text列的权重为D;

  • 创建tsv列更新函数;在表上创建触发器,当更新和新增行时,执行tsv列更新函数。
  • 当一切就绪后,替换下面代码中的“你的查询”并执行:
    SELECT id, meta->>‘title‘ as title, meta FROM (
      SELECT id, meta, tsv
      FROM data_rows, plainto_tsquery(‘你的查询‘) AS q
      WHERE (tsv @@ q)
    ) AS t1 ORDER BY ts_rank_cd(t1.tsv, plainto_tsquery(‘你的查询‘)) DESC LIMIT 5;

    经测试,该查询大约50毫秒即可完成。如果返回文档全文,则会增加大约350毫秒,这更多的可能是受网络负载影响。如果只返回文档中的200个字符,则仅仅增加大约100毫秒。

  • 时间: 2024-10-28 21:34:47

    利用PostgreSQL实现毫秒级全文检索的相关文章

    亿级数据毫秒级查询!ElasticSearch是怎么做到的?

    目录: 1. 一道面试题的引入: 2. 性能优化的杀手锏:Filesystem Cache 3. 数据预热 4. 冷热分离 5. ElasticSearch 中的关联查询 6. Document 模型设计 7. 分页性能优化 一道面试题的引入: 如果面试的时候碰到这样一个面试题:ElasticSearch(以下简称ES) 在数据量很大的情况下(数十亿级别)如何提高查询效率? 这个问题说白了,就是看你有没有实际用过 ES,因为啥?其实 ES 性能并没有你想象中那么好的. 很多时候数据量大了,特别是

    c/c++中sleep()函数毫秒级的实现

    近期看到好多人在问.c/c++中的sleep函数是秒级的,能不能实现毫秒级的呢?当然非常easy.我的写法例如以下 #include <stdio.h> #include <sys/select.h> static void sleep_ms(unsigned int secs) { struct timeval tval; tval.tv_sec=secs/1000; tval.tv_usec=(secs*1000)%1000000; select(0,NULL,NULL,NUL

    在Windows及Linux下获取毫秒级运行时间的方法

    在Windows下获取毫秒级运行时间的方法 头文件:<Windows.h> 函数原型: /*获取时钟频率,保存在结构LARGE_INTEGER中***/ WINBASEAPI BOOL WINAPI QueryPerformanceFrequency( _Out_ LARGE_INTEGER * lpFrequency ); /*获取从某个时间点开始的时钟周期数,保存在结构LARGE_INTEGER中**/ WINBASEAPI BOOL WINAPI QueryPerformanceFreq

    如何统计毫秒级的时间差

    计算毫秒级的时间差算是一个常见的需求吧... 手头上是windows编程的项目,所以首先就想到的是GetTickCount(),但MSDN上这么说: 写个程序试一下吧: 1 #include <stdio.h> 2 #include <windows.h> 3 4 int main(void) 5 { 6 DWORD dwLastTime = GetTickCount(); 7 for (int i = 0; i != 10; ++i) 8 { 9 DWORD dwCurrentT

    C++计时器:毫秒级和微秒级

    1.毫秒级 使用GetTickCount()获取系统启动所经过的毫秒数 #include<iostream> using namespace std; int main(){ DWORD start= ::GetTickCount(); //获取毫秒级数目 Sleep(1000); cout << ::GetTickCount() - start<< endl; system("pause"); } 2. 使用clock() #include <

    WPF毫秒级桌面时钟的实现-C#中Hook(钩子)的应用

    最近由于项目中需要精确记录某些操作的发生时间,但又没有办法打日志,因此写了个小工具,用来记录当前的毫秒级本机时间. (程序内部实现了全局钩子,监听所有的键盘事件,即KeyDown,KeyUp事件.) 工具功能如下: 1.通过任意键盘按键来记录当前时间 2.可以在列表处单击记录当前时间 C#中对于Hook API的包装如下: using System; using System.Collections.Generic; using System.Linq; using System.Reflect

    毫秒级百万数据分页存储过程[欢迎转载]

    数据分页一直是一个经久不衰的话题,在园子里看到了N多高手,都比我厉害, 今天把我使用的分页代码继续分享;请高手手下留情,少拍砖啦...哈哈; 欢迎大家转载!!!! 首先参考园子里的高手方法生成一个百万数据表; 耗时 33 秒; 然后创建分页存储过程;这个是基于SQL 2005 的ROW_NUMBER的, SQL 2000 不适用; SQL 2008 我没有安装,所以也没有测试过!估计应该可以运行. 2种算法可以选择 1. 使用  BETWEEN   ;  2.  TOP  ; 代码中已经注释了.

    shell脚本示例:计算毫秒级、微秒级时间差

    有时候需要计算命令的执行时间长度,可以使用time命令,虽然time命令可以精确到毫秒级,但time命令无法计算一堆命令的执行时间.可以也可以直接使用date命令计算命令执行前后的时间差,但直接使用date命令计算时间差只能精确到秒级.因此,要计算毫秒级或者微秒级的时间长度,需要对date命令的结果进行一番计算转换. 本文只给出了毫秒级时间差的计算方法,若要计算微秒级时间差,对脚本稍作修改即可. 脚本如下: #!/bin/bash # filename: msec_diff.sh functio

    Linux Shell获得毫秒级的时间戳

    在linux Shell中并没有毫秒级的时间单位,只有秒和纳秒其实这样就足够了,因为纳秒的单位范围是(000000000..999999999),所以从纳秒也是可以的到毫秒的. current=`date "+%Y-%m-%d %H:%M:%S"`     #获取当前时间,例:2015-03-11 12:33:41        timeStamp=`date -d "$current" +%s`      #将current转换为时间戳,精确到秒 currentT