【问题标题】:indexing and query high dimensional data in postgreSQL在 postgreSQL 中索引和查询高维数据
【发布时间】:2016-02-15 09:02:18
【问题描述】:

我想索引高度维度的数据(128 维的整数向量在 [0,254] 范围内是可能的):

| id |      vector       |
|  1 | { 1, 0, ..., 254} |
|  2 | { 2, 128, ...,1}  |
|  . | { 1, 0, ..., 252} |
|  n | { 1, 2, ..., 251} |

我看到 PostGIS 实现了 R-Trees。那么我可以在 PostGIS 中使用这些树来索引和查询 Postgres 中的多维向量吗?

我也看到有index implementation for int arrays

现在我对如何执行查询有疑问。
我可以对整数数组执行 knn 搜索和半径搜索吗? 也许我还必须定义自己的距离函数。这可能吗?我想使用Manhattan distance(块距离)进行查询。

我还可以将我的向量表示为具有模式v1;v2;...;vn 的二进制字符串。这有助于执行搜索吗?

例如,如果我有这两个字符串:

1;2;1;1
1;3;2;2

这两个字符串之间的结果/距离应该是 3。

【问题讨论】:

  • 对于你的例子,它并不完全清楚 - 你想看看有多少元素不同(levenshtein 距离)或它们有多少不同(曼哈顿距离),例如 (3-2) + ( 2-1) + (2-1)。
  • @hruske:我想知道它们有多大不同(曼哈顿、出租车、街区)- 距离

标签: sql postgresql multidimensional-array indexing postgresql-9.3


【解决方案1】:

也许更好的选择是cube extension,因为您感兴趣的区域不是单个整数,而是全向量。

Cube 支持 GiST 索引,Postgres 9.6 也会为 Cube 带来 KNN 索引,支持euclidean, taxicab (aka Manhattan) and chebishev distances

9.6 仍在开发中有点烦人,但是将多维数据集扩展补丁向后移植到 9.5 没有问题,我是根据经验说的。

希望 128 个维度仍然足以获得 meaningful results

怎么做?

首先有一个示例表:

create extension cube;
create table vectors (id serial, vector cube);

用示例数据填充表格:

insert into vectors select id, cube(ARRAY[round(random()*1000), round(random()*1000), round(random()*1000), round(random()*1000), round(random()*1000), round(random()*1000), round(random()*1000), round(random()*1000)]) from generate_series(1, 2000000) id;

然后尝试选择:

explain analyze SELECT * from vectors
order by cube(ARRAY[966,82,765,343,600,718,338,505]) <#> vector asc limit 10;
                                                           QUERY PLAN                                                           
--------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=123352.07..123352.09 rows=10 width=76) (actual time=1705.499..1705.501 rows=10 loops=1)
   ->  Sort  (cost=123352.07..129852.07 rows=2600000 width=76) (actual time=1705.496..1705.497 rows=10 loops=1)
         Sort Key: (('(966, 82, 765, 343, 600, 718, 338, 505)'::cube <#> vector))
         Sort Method: top-N heapsort  Memory: 26kB
         ->  Seq Scan on vectors  (cost=0.00..67167.00 rows=2600000 width=76) (actual time=0.038..998.864 rows=2600000 loops=1)
 Planning time: 0.172 ms
 Execution time: 1705.541 ms
(7 rows)

我们应该创建一个索引:

create index vectors_vector_idx on vectors (vector);

有帮助吗:

explain analyze SELECT * from vectors
order by cube(ARRAY[966,82,765,343,600,718,338,505]) <#> vector asc limit 10;

--------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=0.41..1.93 rows=10 width=76) (actual time=41.339..143.915 rows=10 loops=1)
   ->  Index Scan using vectors_vector_idx on vectors  (cost=0.41..393704.41 rows=2600000 width=76) (actual time=41.336..143.902 rows=10 loops=1)
         Order By: (vector <#> '(966, 82, 765, 343, 600, 718, 338, 505)'::cube)
 Planning time: 0.146 ms
 Execution time: 145.474 ms
(5 rows)

在 8 个维度上,它确实有帮助。

【讨论】:

  • 我也可以将向量表示为二进制字符串(v1;v2;v3...;vn)。有没有将二进制字符串与曼哈顿距离进行比较的选项?
  • 出租车距离也称为曼哈顿距离。 en.wikipedia.org/wiki/Taxicab_geometry
【解决方案2】:

(所选答案的附录)

对于想要超过 100 个维度的人,请注意:a 100 dimensions limit in cube extension

棘手的部分是 postgres 允许您创建超过 100 个维度的立方体。当您尝试恢复备份时,它被拒绝(最糟糕的时候意识到这一点)。

按照文档中的建议,我修补了多维数据集扩展以支持更多维度。我为它制作了一个 docker 镜像,您可以查看 Dockerfile 以了解如何自己操作,来自 github repos

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-07
    • 1970-01-01
    • 1970-01-01
    • 2015-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多