PostgreSQL 多字段任意组合搜索的性能

标签

PostgreSQL , 多字段搜索 , 任意字段搜索


背景

PostgreSQL 多字段,任意组合搜索,有三种优化手段:

1、gin索引(支持任意字段组合的查询)

《宝剑赠英雄 - 任意组合字段等效查询, 探探PostgreSQL多列展开式B树 (GIN)》

2、bloom索引(支持任意只读组合的等值查询)

《PostgreSQL 9.6 黑科技 bloom 算法索引,一个索引支撑任意列组合查询》

3、每个单列btree索引(支持任意字段组合的查询)

《PostgreSQL bitmapAnd, bitmapOr, bitmap index scan, bitmap heap scan》

例子

create table test(c1 int, c2 int, c3 int, c4 int, c5 int);

bloom, gin, multi-btree几种索引创建方法

1、bloom

postgres=# create extension bloom ;
CREATE EXTENSION
postgres=# create index idx_test12_1 on test12 using bloom (c1,c2,c3,c4,c5);
CREATE INDEX
postgres=# explain select * from test12 where c1=1;
                                 QUERY PLAN
----------------------------------------------------------------------------
 Bitmap Heap Scan on test12  (cost=13.95..20.32 rows=8 width=20)
   Recheck Cond: (c1 = 1)
   ->  Bitmap Index Scan on idx_test12_1  (cost=0.00..13.95 rows=8 width=0)
         Index Cond: (c1 = 1)
(4 rows)
postgres=# explain select * from test12 where c1=1 and c2=1;
                                 QUERY PLAN
----------------------------------------------------------------------------
 Bitmap Heap Scan on test12  (cost=18.20..19.42 rows=1 width=20)
   Recheck Cond: ((c1 = 1) AND (c2 = 1))
   ->  Bitmap Index Scan on idx_test12_1  (cost=0.00..18.20 rows=1 width=0)
         Index Cond: ((c1 = 1) AND (c2 = 1))
(4 rows)
postgres=# explain select * from test12 where c1=1 or c2=1;
                                    QUERY PLAN
----------------------------------------------------------------------------------
 Bitmap Heap Scan on test12  (cost=27.91..38.16 rows=17 width=20)
   Recheck Cond: ((c1 = 1) OR (c2 = 1))
   ->  BitmapOr  (cost=27.91..27.91 rows=17 width=0)
         ->  Bitmap Index Scan on idx_test12_1  (cost=0.00..13.95 rows=8 width=0)
               Index Cond: (c1 = 1)
         ->  Bitmap Index Scan on idx_test12_1  (cost=0.00..13.95 rows=8 width=0)
               Index Cond: (c2 = 1)
(7 rows)

2、gin

postgres=# create extension btree_gin;
CREATE EXTENSION
postgres=# create index idx_test12_1 on test12 using gin (c1,c2,c3,c4,c5);
CREATE INDEX
postgres=# explain select * from test12 where c1=1 or c2=1;
                                   QUERY PLAN
---------------------------------------------------------------------------------
 Bitmap Heap Scan on test12  (cost=4.94..15.19 rows=17 width=20)
   Recheck Cond: ((c1 = 1) OR (c2 = 1))
   ->  BitmapOr  (cost=4.94..4.94 rows=17 width=0)
         ->  Bitmap Index Scan on idx_test12_1  (cost=0.00..2.46 rows=8 width=0)
               Index Cond: (c1 = 1)
         ->  Bitmap Index Scan on idx_test12_1  (cost=0.00..2.46 rows=8 width=0)
               Index Cond: (c2 = 1)
(7 rows)  

postgres=# explain select * from test12 where c1=1 and c2=1;
                                QUERY PLAN
---------------------------------------------------------------------------
 Bitmap Heap Scan on test12  (cost=3.60..4.82 rows=1 width=20)
   Recheck Cond: ((c1 = 1) AND (c2 = 1))
   ->  Bitmap Index Scan on idx_test12_1  (cost=0.00..3.60 rows=1 width=0)
         Index Cond: ((c1 = 1) AND (c2 = 1))
(4 rows)

3、multi-btree

postgres=# drop index idx_test12_1 ;
DROP INDEX
postgres=# create index idx_test12_1 on test12 using btree(c1);
CREATE INDEX
postgres=# create index idx_test12_2 on test12 using btree(c2);
CREATE INDEX
postgres=# create index idx_test12_3 on test12 using btree(c3);
CREATE INDEX
postgres=# create index idx_test12_4 on test12 using btree(c4);
CREATE INDEX
postgres=# create index idx_test12_5 on test12 using btree(c5);
CREATE INDEX  

postgres=# explain select * from test12 where c1=1 and c2=1;
                                   QUERY PLAN
---------------------------------------------------------------------------------
 Bitmap Heap Scan on test12  (cost=3.08..4.29 rows=1 width=20)
   Recheck Cond: ((c2 = 1) AND (c1 = 1))
   ->  BitmapAnd  (cost=3.08..3.08 rows=1 width=0)
         ->  Bitmap Index Scan on idx_test12_2  (cost=0.00..1.41 rows=8 width=0)
               Index Cond: (c2 = 1)
         ->  Bitmap Index Scan on idx_test12_1  (cost=0.00..1.41 rows=8 width=0)
               Index Cond: (c1 = 1)
(7 rows)  

postgres=# explain select * from test12 where c1=1 or c2=1;
                                   QUERY PLAN
---------------------------------------------------------------------------------
 Bitmap Heap Scan on test12  (cost=2.83..13.09 rows=17 width=20)
   Recheck Cond: ((c1 = 1) OR (c2 = 1))
   ->  BitmapOr  (cost=2.83..2.83 rows=17 width=0)
         ->  Bitmap Index Scan on idx_test12_1  (cost=0.00..1.41 rows=8 width=0)
               Index Cond: (c1 = 1)
         ->  Bitmap Index Scan on idx_test12_2  (cost=0.00..1.41 rows=8 width=0)
               Index Cond: (c2 = 1)
(7 rows)

gin, bloom, btree bitmap scan的性能如何呢?

1600个列的宽表,任意字段组合搜索性能

1、建表

postgres=# do language plpgsql $$
declare
  sql text;
begin
  sql := 'create table test1 (';
  for i in 1..1600 loop
    sql := sql||' c'||i||' int2 default random()*100,';
  end loop;
  sql := rtrim(sql,',');
  sql := sql||')';
  execute sql;   

  for i in 1..1600 loop
    execute 'create index idx_test1_'||i||' on test1 (c'||i||')';
  end loop;
end;
$$;
DO

2、写入测试数据

postgres=# insert into test1 (c1)  select generate_series(1,10000);
INSERT 0 10000

3、测试脚本

vi test.sql  

\set c2 random(1,100)
\set c3 random(1,100)
\set c4 random(1,100)
\set c5 random(1,100)
\set c6 random(1,100)
\set c7 random(1,100)
select c1600 from test1 where c2=:c2 and c3=:c3 and c4=:c4 or (c5=:c5 and c6=:c6 and c7=:c7);

4、测试

pgbench -M prepared -n -r -P 1 -f ./test.sql -c 64 -j 64 -T 120

5、性能

progress: 33.0 s, 208797.8 tps, lat 0.307 ms stddev 0.016
progress: 34.0 s, 208516.0 tps, lat 0.307 ms stddev 0.032
progress: 35.0 s, 208574.0 tps, lat 0.307 ms stddev 0.050
progress: 36.0 s, 208858.2 tps, lat 0.306 ms stddev 0.013
progress: 37.0 s, 208686.8 tps, lat 0.307 ms stddev 0.043
progress: 38.0 s, 208764.2 tps, lat 0.307 ms stddev 0.013

注意,使用prepared statement,可以减少硬解析,提高性能。

从测试来看,任意字段的搜索,可以达到0.3毫秒的响应。

时间: 2024-12-31 16:18:19

PostgreSQL 多字段任意组合搜索的性能的相关文章

HTAP数据库 PostgreSQL 场景与性能测试之 20 - (OLAP) 用户画像圈人场景 - 多个字段任意组合条件筛选与透视

标签 PostgreSQL , HTAP , OLTP , OLAP , 场景与性能测试 背景 PostgreSQL是一个历史悠久的数据库,历史可以追溯到1973年,最早由2014计算机图灵奖得主,关系数据库的鼻祖Michael_Stonebraker 操刀设计,PostgreSQL具备与Oracle类似的功能.性能.架构以及稳定性. PostgreSQL社区的贡献者众多,来自全球各个行业,历经数年,PostgreSQL 每年发布一个大版本,以持久的生命力和稳定性著称. 2017年10月,Pos

高并发低基数多字段任意组合查询的优化

1.问题 首先解释一下这个标题里出现的"低基数多字段任意组合查询"指什么东西.这里是指满足下面几个条件的查询: 1. 检索条件中涉及多个字段条件的组合 2. 这些字段的组合是不确定的 3. 每个单独字段的选择性都不好 这种类型的查询的使用场景很多,比如电商的商品展示页面.用户会输入各种不同查询条件组合:品类,供应商,品牌,促销,价格等等...,最后往往还要对结果进行排序和分页. 这类问题令人头疼的地方在于: 1. 记录数量众多,如果进行全表扫描性能低下无法满足高并发访问的要求. 2.

多字段,任意组合条件查询(0建模) - 毫秒级实时圈人 实践

标签 PostgreSQL , 数组 , GIN索引 , 任意字段组合查询 , 圈人 , ToB分析型业务 , 建模 背景 你也许在一家ToB的数据分析公司,你可能设计了一张表(包括用户标识,及若干已经统计好的的属性值),你也许收集了一些用户的数据,你也许要为客户提供报表,你也许需要为客户提供任意属性值的组合查询,并快速的返回结果给用户. 这些需求应该是非常常见的ToB的数据平台公司的形态,头痛的问题无法建模,因为B端的需求无法捉摸,任意组合查询.要求实时响应. 你的客户数据也许有几十亿上百亿,

通用数据库显示程序,能调任意库,任意字段,多关键字搜索,自动分页通用

程序|分页|关键字|数据|数据库|显示 数据库显示程序,能调任意库,任意字段,多关键字搜索,自动分页. 阿余经常写一些数据库相关的程序,当然离不开显示库中的数据了,说实话,做这样的程序真是无聊啊,所以,阿余就想写个函数,一个通用的数据库显示函数.要求如下:   1. 能显示指定的字段,当然,字段名和显示的文字可以不一样.  2. 能同时按多个字段进行查询,支持模糊和精确两种查询方式.  3. 有横向排列和纵向排列字段两种显示方式.  4. 能自动分页.  5. 能设定每页显示多少条记录.好啦,要

任意列搜索之 列存储优化

标签 PostgreSQL , 列存储 , shard , 切片 , 大块 , 小块 , sort , 块级索引 , bitmap scan , 索引延迟 , 归整 背景 数据分析系统,决策系统的数据量通常非常庞大,属性(列)非常多,可能涉及到任意列的组合条件查询,筛选结果.聚合结果.多维分析等. 这种场景如何优化能满足实时的响应需求呢? PostgreSQL中有一些技术,可以满足此类场景. 1. 内置bitmapAnd bitmapOr,使用任意字段的索引搜索时,可以快速跳过不满足条件的块,快

PgSQL · 应用案例 · GIN索引在任意组合查询中的应用

背景 很多人小时候都有一个武侠梦,独孤求败更是金庸武侠小说里的一位传奇人物. 纵横江湖三十馀载,杀尽仇寇奸人,败尽英雄豪杰,天下更无抗手,无可奈何,惟隐居深谷,以雕为友. 呜呼,生平求一敌手而不可得,诚寂寥难堪也. 独孤老前辈的佩剑描写非常有意思,从使用的佩剑,可以看出一个人的武功修为. 第一柄是一柄青光闪闪的无名利剑.「凌厉刚猛,无坚不摧,弱冠前以之与河朔群雄争锋.」 第二柄是紫薇软剑,「三十岁前所用,误伤义士不祥,乃弃之深谷.」 第三柄是玄铁重剑,「重剑无锋,大巧不工,四十岁之前恃之横行天下

PostgreSQL 最佳实践 - 任意时间点恢复源码分析

背景 我们知道PostgreSQL是支持任意时间点恢复的,那么背后的原理是什么? 本文将对PG的时间点恢复进行详细的讲解,帮助用户理解. 本文涉及源码参考PostgreSQL 9.2.2版本. 时间点恢复涉及的参数 我们知道PostgreSQL 支持PITR, 基于时间点的恢复. 通过配置recovery.conf可以指定3种恢复目标, 如下 : recovery_target_name (string) This parameter specifies the named restore po

SQL语句实现表中字段的组合累加排序

有表如下: id in out index 1 10 12 2 2 9 8 2 3 12 8 3 1 9 9 3 1 12 0 3 2 5 18 2 2 20 0 2 这三个字段均为integer类型 现要求如下: 1.按index=2查找 2.将所有id相同的和在一起,数据要加在一起 3.最后呈现的数据要按in+out进行排序,按由大到小 为满足以上的要求:设计的SQL语句如下(假设表名为tab) 复制代码 代码如下:select id,sum(in) as in,sum(out) as ou

一个通用数据库显示程序,能调任意库,任意字段,多关键字搜索,自动分页

程序|分页|关键字|数据|数据库|显示 . 阿余经常写一些数据库相关的程序,当然离不开显示库中的数据了,说实话,做这样的程序真是无聊啊,所以,阿余就想写个函数,一个通用的数据库显示函数.要求如下: 1. 能显示指定的字段,当然,字段名和显示的文字可以不一样.2. 能同时按多个字段进行查询,支持模糊和精确两种查询方式.3. 有横向排列和纵向排列字段两种显示方式.4. 能自动分页.5. 能设定每页显示多少条记录.好啦,要求大至就是这样了.根据这个要求,阿余写了下面的函数.实际上,这里阿余写了两个函数