【DB吐槽大会】第50期 - PG GiST距离排序操作符和过滤无法同时使用索引

简介: 大家好,这里是DB吐槽大会,第50期 - PG GiST距离排序操作符和过滤无法同时使用索引

背景


1、产品的问题点

  • PG GiST距离排序操作符和过滤无法同时使用索引

2、问题点背后涉及的技术原理

  • PG GiST索引支持空间距离排序, 例如按距离某个经纬度点的距离排序, 返回表里面的经纬度点.
  • PG 支持距离操作符, 支持排序功能, 同时支持返回距离值.
  • 但是距离过滤不能使用索引

例子:

create extension btree_gist;  
postgres=# \do  
                                             List of operators  
 Schema | Name |        Left arg type        |       Right arg type        |   Result type    | Description   
--------+------+-----------------------------+-----------------------------+------------------+-------------  
 public | <->  | bigint                      | bigint                      | bigint           |   
 public | <->  | date                        | date                        | integer          |   
 public | <->  | double precision            | double precision            | double precision |   
 public | <->  | integer                     | integer                     | integer          |   
 public | <->  | interval                    | interval                    | interval         |   
 public | <->  | money                       | money                       | money            |   
 public | <->  | oid                         | oid                         | oid              |   
 public | <->  | real                        | real                        | real             |   
 public | <->  | smallint                    | smallint                    | smallint         |   
 public | <->  | time without time zone      | time without time zone      | interval         |   
 public | <->  | timestamp with time zone    | timestamp with time zone    | interval         |   
 public | <->  | timestamp without time zone | timestamp without time zone | interval         |   
create table t_age(id int, age int);    
insert into t_age select generate_series(1,10000000), random()*120;    
create index idx_t_age_1 on t_age using gist (age);    
select * from t_age     
where     
(age <-> 25) < 1     
order by age <-> 25     
limit 100000;    
 Limit  (cost=0.42..10245.61 rows=100000 width=12) (actual time=0.161..8126.988 rows=83248 loops=1)  
   Output: id, age, ((age <-> 25))  
   Buffers: shared hit=9523157  
   ->  Index Scan using idx_t_age_1 on public.t_age  (cost=0.42..341506.11 rows=3333326 width=12) (actual time=0.160..8115.150 rows=83248 loops=1)  
         Output: id, age, (age <-> 25)  
         Order By: (t_age.age <-> 25)  
         Filter: ((t_age.age <-> 25) < 1)  
         Rows Removed by Filter: 9916752  
         Buffers: shared hit=9523157  
 Planning Time: 0.077 ms  
 Execution Time: 8133.808 ms  
(11 rows)  
postgres=# set enable_seqscan=off;  
SET  
postgres=# explain select * from t_age where (age <-> 25) <1 limit 100000;  
                                     QUERY PLAN                                        
-------------------------------------------------------------------------------------  
 Limit  (cost=10000000000.00..10000005827.44 rows=100000 width=8)  
   ->  Seq Scan on t_age  (cost=10000000000.00..10000194247.66 rows=3333326 width=8)  
         Filter: ((age <-> 25) < 1)  
(3 rows)  

3、这个问题将影响哪些行业以及业务场景

  • 影响最大的时基于地理位置的互联网业务, 例如社交、O2O、出行等

4、会导致什么问题?

  • 当需要搜索附近的N个点, 并且距离M以内的双重需求时, 不能同时使用1个索引来满足. (要么只能用于排序, 要么只能用于where过滤)
  • 需要额外的filter计算, 如果满足条件(距离M以内)的记录数不足N条, 则导致扫描整个索引, 性能急剧下降.

5、业务上应该如何避免这个坑

  • 可以使用function来解决这个问题, 每次filter判定是否已越界.

6、业务上避免这个坑牺牲了什么, 会引入什么新的问题

  • 需要自定义函数, 开发成本增加.

7、数据库未来产品迭代如何修复这个坑

  • 希望能直接在内核层面支持, 同一个index既能支持按距离过滤又能支持按距离排序输出.
相关文章
|
Oracle 关系型数据库
查询Oracle字段列的最大值并查询多列数据的实现方法
查询Oracle字段列的最大值并查询多列数据的实现方法
2099 0
|
4月前
|
Oracle 关系型数据库
Oracle查询优化-根据条件取不同列的值排序
【1月更文挑战第3天】【1月更文挑战第9篇】有时排序的要求会比较复杂,比如,领导对工资在 1000 到 2000元之间的员工更感兴趣,于是要求工资在这个范围的员工要排在前面,以便优先查看。这种情况就不仅仅使用ORDER BY了。
130 0
|
关系型数据库 MySQL Java
mysql字段的细节(查询自定义的字段[意义:行列转置];UNION ALL;case-when)
mysql字段的细节(查询自定义的字段[意义:行列转置];UNION ALL;case-when)
187 0
mysql字段的细节(查询自定义的字段[意义:行列转置];UNION ALL;case-when)
|
SQL 算法 搜索推荐
【DB吐槽大会】第77期 - PG 不支持索引随机采样
大家好,这里是DB吐槽大会,第77期 - PG 不支持索引随机采样
|
SQL 关系型数据库 数据库
PostgreSQL 设计优化case - 大宽表任意字段组合查询索引如何选择(btree, gin, rum) - (含单个索引列数超过32列的方法)
标签 PostgreSQL , adhoc查询 , 大宽表 , 任意字段组合查询 , 索引 , btree , gin , rum 背景 大宽表,任意字段组合查询,透视。是实时分析系统中的常见需求: 1、实时写入。
2500 0
|
关系型数据库 PostgreSQL
PostgreSQL 快速返回表上某列的唯一值(枚举值) - pg_stats.most_common_vals
标签 PostgreSQL , 统计信息 , 唯一值 , 枚举值 背景 PostgreSQL的列统计信息中包含一项高频词,同时包含一项唯一值个数。 pg_stats.n_distinct pg_stats.most_common_vals 同时PostgreSQL允许用户自定义统计信息柱状图BUCKET的个数。
1574 0
|
Oracle 关系型数据库 索引
oracle优化一则--不走索引
字段类型转换会造成无法使用索引的情况,如果非要进行转换,可以创建带有转换类型的索引,函数索引。
14505 0