postgres中的manydimentional距离

时间:2014-06-25 09:45:44

标签: postgresql postgis

Postgres / Postgis支持点之间的距离计算,按给定点的距离排序等等,我试图滥用此设施:)

这是一个例子,只是为了说明我试图做的事情。

       Width    Height  Thickness   Hue Lightness   Saturation     
Item1  220      157     100         270 60          75     
Item2  221      199     105         280 60          75     
Item3  210      150     105         100 40          75   

暂时忽略这些功能,要找到下表中与物理尺寸类似的近似匹配项:

SELECT * FROM items
ORDER BY sqrt((i1.width-i2.height)*(i1.width-i2.height)
            + (i1.width-i2.height)*(i1.width-i2.height)
            + (i1.thickness-i2.thickness)*(i1.thickness-i2.thickness))

(称之为pseudosql :))

我们可以将第4-6个属性视为维度,使得类似(或" close")颜色对于每个属性具有相似的值。我们可以通过添加这些字段来扩展上述查询。

现在,Postgres似乎能够通过索引来做一些相当不错的事情,这样可以大大加快上述查询速度,但数据类型似乎只有4个维度。

对于数百万条记录,计算的更好的解决方案是什么,更常见的是对10个尺度(或"尺寸")的记录相似性进行排序?

我目前正在考虑3个4D点并按3点的距离排序。

如果没有Postgis的话,我想问题是: -

在一个包含如下项目的表中,最快的方法是使用10个值输入(每个val字段一个)之间的差值之和进行排序,利用任何可能的,边界框,空间或其他索引等

例如

SELECT * FROM items
ORDER BY ((item_val1-xxxx)*(item_val1-xxxx)
        * (item_val2-yyyy)*(item_val2-yyyy)
        * ......
        * (item_val10-zzzz)*(item_val10-zzzz))

其中xxxx,yyyy,zzzz表示前端应用程序中输入的值

item_name: string
item_val1: int
item_val2: int
item_val3: int
item_val4: int
item_val5: int
item_val6: int
item_val7: int
item_val8: int
item_val9: int
item_val10: int

非常感谢任何想法/替代方案。

1 个答案:

答案 0 :(得分:4)

PostGIS非常适合GIS,但正如John B所指出的那样,cube extension非常适合用于 n - 维度Eucludian距离。

添加扩展名,并将具有GiST索引的新列添加到表中:

CREATE EXTENSION cube;
ALTER TABLE items ADD COLUMN point cube;
CREATE INDEX items_point_idx ON items USING gist (point);

填充point字段,您可能希望通过将列乘以标量(2为2,0.5为一半等)来加权某些属性高于其他属性:

UPDATE items SET
  point = cube(array[width, height, thickness, hue, lightness, saturation]);

现在使用自联接找到一些距离:

SELECT i1.id, i1.point, i2.id, i2.point, cube_distance(i1.point, i2.point)
FROM items i1, items i2
WHERE i1.id < i2.id
ORDER BY cube_distance(i1.point, i2.point);