副标题[/!--empirenews.page--]
人与世界万物的互动会产生大量的时空数据。那么,当我们需要随时调用过去的数据时,改怎么办?尤其是面对各种海量、多维度的数据库,如果没有高效的搜索方法,我们只能望洋兴叹、束手无策。

别担心,本文将用详细的代码,手把手来传授高效搜索法的绝技!
对象数据分类
对象数据可分为两种类型:静态数据(相对静态,例如建筑)和动态数据(例如人的活动和物联网传感器的活动)。
按研究需求分类的索引
时空快照搜索
有些对象以相对较低的频率生成数据。例如,建筑物和道路等惰性物体可能在数年内不会发生任何变化。如果将为这些对象生成的数据写入数据库,并按时间范围查询数据(例如,查询日期为2017-07-01至2017-07-02),则可能找不到与这些对象相关的任何数据。原因很简单,在这段时间内数据库根本没有相关数据输入。
时空行为数据搜索
时空行为数据是指从人的活动等动态对象中获取数据。
例如,分析特定地区特定时间段内某一人群的特征,或者分析大学周边人群在工作日和周末构成的差异。
时空快照不属于本文的讨论范围。现在,我们看看如何搜索时空行为数据。
数据结构
时空行为数据包含三个属性:时间、空间和对象。
非结构化索引:
- create table test(
- id int8,
- crt_time timestamp, -- Time
- pos geometry, -- Location
- obj jsonb -- Object description
- );
除了应用于JSON,结构化数据还可以用于对象描述。例如:
- create table test(
- id int8,
- crt_time timestamp, -- Time
- pos geometry, -- Location
- c1 int, -- Some property examples
- c2 int,
- c3 text,
- c4 float8,
- c5 int,
- c6 date,
- c7 text,
- c8 int,
- c9 int,
- c10 int
- );
时空行为数据的SQL查询实例
- select * from test
- where
- pos <-> ? < ?
- and crt_time between ? and ?
- and ( (c1 = ? and c2 between ? and ?) or c10=?)
- ...
- ;
优化方法
考虑运用以下知识:
时间序列BRIN索引
crt_time字段是一个时间序列字段,表示生成数据的时间。在PostgreSQL堆存储中,存储和该字段的值具有很强的线性相关性。
因此,BRIN索引很合适。
使用BRIN索引来代替分区表进行TPC-H测试。大范围搜索的性能甚至优于使用分区表时的功能。
- create index idx_test_1 on test using brin(crt_time);
空间索引
显然,空间检索需要空间索引。PostgreSQL中可以使用三种方法实现空间检索。
1. 几何类型的GIST索引
- create index idx_test_2 on test using gist(pos);
该索引支持空间KNN搜索和空间位置确定等功能。
2. 几何类型的主索引
- create index idx_test_2 on test using spgist(pos);
该索引支持空间KNN搜索和空间位置确定等功能。
3. Geohash和B-tree索引(将经度和纬度转换为Geohash并为hash值创建B-tree索引)。只需使用表达式索引。
- create index idx_test_3 on test using btree( ST_GeoHash(pos,15) );
此索引支持前缀搜索(其能落实编码地理信息网格中包含的关系)。它属于有损索引,需要二次过滤。
GiST和SPGiST空间索引能够找到准确的地理位置信息,优于GEOHASH索引。但是,查询信息时需要特别注意。
GIN 索引
此索引类型的目标是对象属性字段JSONB或多个结构化对象属性字段。只需使用GIN索引。
例如:
- create extension btree_gin;
非结构化索引:
- create index idx_test_4 on test using gin( obj );
结构化索引:
- create index idx_test_4 on test using gin( c1,c2,c3,c4,c5,c6,c7,c8,c9 );
BitmapAnd和BitmapOr
在上一节中,根据数据类型和查询需求可以为不同的查询维度选择相应的索引。
但是,可以同时使用这些索引吗? PostgreSQL为多个索引提供bitmapAnd及bitmapOr接口。它们可以组合多个索引,减少需要扫描的数据库数量。
- Heap, one square = one page:
- +---------------------------------------------+
- |c____u_____X___u___X_________u___cXcc______u_|
- +---------------------------------------------+
- Rows marked c match customers pkey condition.
- Rows marked u match username condition.
- Rows marked X match both conditions.
- Bitmap scan from customers_pkey:
- +---------------------------------------------+
- |100000000001000000010000000000000111100000000| bitmap 1
- +---------------------------------------------+
- One bit per heap page, in the same order as the heap
- Bits 1 when condition matches, 0 if not
- Bitmap scan from ix_cust_username:
- +---------------------------------------------+
- |000001000001000100010000000001000010000000010| bitmap 2
- +---------------------------------------------+
- Once the bitmaps are created a bitwise AND is performed on them:
- +---------------------------------------------+
- |100000000001000000010000000000000111100000000| bitmap 1
- |000001000001000100010000000001000010000000010| bitmap 2
- &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
- |000000000001000000010000000000000010000000000| Combined bitmap
- +-----------+-------+--------------+----------+
- | | |
- v v v
- Used to scan the heap only for matching pages:
- +---------------------------------------------+
- |___________X_______X______________X__________|
- +---------------------------------------------+
- The bitmap heap scan then seeks to the start of each page and reads the page:
- +---------------------------------------------+
- |___________X_______X______________X__________|
- +---------------------------------------------+
- seek------->^seek-->^seek--------->^
- | | |
- ------------------------
- only these pages read
(编辑:西安站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|