2016-04-15 76 views
1

我有以下表格是postgres(postgis)。这两个表有1,不同类型的字符第2,第3列(9000)和类型“几何”的第4列(包含点几何(纬度,经度)):加入两张表

Table1 
Column1  Column2    Column3 the_geom 
Oklahoma  numericalValue1  719  NULL 
Oklahoma  geometry   NULL  (34.6,95.3) 
Oklahoma  liesIn    America NULL 

Table2 
Column1  Column2   Column3  the_geom 
Mississippi liesIn    America  NULL 
Mississippi geometry   NULL  (32.7,-89.53) 
Mississippi numericalValue2 15.3  NULL 

我想运行下面的查询在表1和表2上执行空间连接。问题中显示的表1和表2是玩具表,在我的实际数据集中,它们每个包含100万行。当我运行下面给出的查询时,我发现我的查询需要很长时间(超过10小时)才能运行。有人可以建议,如果有什么方法可以通过重新构建查询来优化查询。

select * from Table1 s1, Table1 s2, Table1 s3, Table2 s4, Table2 s5, Table2 s6 where 
s1.column2='numericalValue1' and  
s2.column2='geometry' and 
s3.column2='liesIn' and 
s1.column1=s2.column1 and 
s2.column1=s3.column1 and 
s4.column2='liesIn' and 
s5.column2='geometry' and 
s6.column2='numericalValue2' and 
s4.column1=s5.column1 and 
s5.column1=s6.column1 and 
ST_DWithin(s2.the_geom, s5.the_geom, 5) 
order by (cast(s1.column3 as double precision)+cast(s6.column3 as double precision)) 
limit 1; 
+1

这是一个可怕的数据库设计。难怪你正面临性能问题。数据库是关于彼此相关的实体,例如国家和国家,每个国家都有自己的属性。所以你应该有一个国家表格和一张州表格,每个州的记录都会指向一个国家,有一个位置等等。然而,你有一件由三件事组成的“事物”,它们的组合构成了一个虚拟记录的属性,再加上它的适当位置。你甚至有两次。改变你的数据模型,一切都会好的。 –

回答

2
  1. 交换轴顺序,使您的几何形状(XY)或(长LAT)
  2. 如果你没有梗概空间索引,然后如何添加一个调查
  3. 我假设你正在使用SRID = 4326或EPSG:4326,它有度数单位。所以5000万的距离是不合逻辑的,并且会做很长时间的交叉连接。尝试使用更小的距离,例如0.01度,或者使用geography类型来调查使用线性距离或其他技巧。
+0

感谢您的回答。 ST_DWithin用于距离的度量单位是米。正确?如果我错了,请纠正我。我还使用了GIST索引,交换轴顺序,使距离= 50000(相当于50公里)。仍然postgres需要很多时间 –

+0

@JannatArora如果你想使用ST_DWithin的度量距离,你可能想调查'geography'类型。这通常是一个棘手的细节,因为并不是每个人都有一个解决方案(例如更改数据库类型,更改SRID,创建地理索引等) –

+0

谢谢,是否可以将数据类型从几何到地理,如果是的话,怎么样? –

1

添加到@ MikeT的回答,首先确保您有column2/predicate两个表上subject,还有一个是指数。

我想说,100万行不是那么多,即使是顺序扫描也会在几秒钟内完成。如果一个查询花费的时间超过了1-2分钟(更不用说10个小时了!),我们有充分的理由相信查询中的某些内容是关闭的(就像在这种情况下,正如Mike所说的,s2和s5之间的虚拟交叉连接)十亿个元组),或者查询需要丢失索引。

我发现使用连接非常有用(与where子句中的所有连接条件相反),使调试查询更容易。例如,下面的查询与您的查询完全相同,但您可以轻松地注释s1,s3,s4和s6上的连接以尝试隔离并查明问题。

select * 
from Table1 s2 
join Table2 s5 on (ST_DWithin(s2.the_geom, s5.the_geom, 50000000)) 
join Table1 s1 on (s1.subject=s2.subject and s1.column2='numericalValue1') 
join Table1 s3 on (s2.subject=s3.subject and s3.column2='liesIn') 
join Table2 s4 on (s4.subject=s5.subject and s4.column2='liesIn') 
join Table2 s6 on (s5.subject=s6.subject and s6.predicate='numericalValue2') 
where s2.column2='geometry' and s5.column2='geometry' 
order by (cast(s1.column3 as double precision)+cast(s6.column3 as double precision)) 
limit 1