为什么这个postgresql查询这么慢?

时间:2010-06-08 00:40:16

标签: sql database postgresql indexing

我不是数据库专家,但我有足够的知识让自己陷入困境,就像这里的情况一样。此查询

SELECT DISTINCT p.* 
  FROM points p, areas a, contacts c 
 WHERE (    p.latitude > 43.6511659465 
        AND p.latitude < 43.6711659465 
        AND p.longitude > -79.4677941889 
        AND p.longitude < -79.4477941889) 
   AND p.resource_type = 'Contact' 
   AND c.user_id = 6

非常慢。 points表的记录少于2000条,但执行大约需要8秒。纬度和经度列上有索引。删除隐含resource_type和user_id的子句没有区别。

纬度和经度字段都被格式化为数字(15,10) - 我需要精度进行一些计算。

此项目中有许多其他查询,其中比较了点,但没有执行时间问题。发生了什么事?

4 个答案:

答案 0 :(得分:11)

您是否忘记了实际查询中的内容?它缺少三个表之间的ANSI-89连接,为您提供笛卡尔积,但只提取POINTS记录。

答案 1 :(得分:5)

您正在加入三个表,p,a和c,但您没有指定如何将它们连接在一起。您得到的是在符合条件的所有表中的所有行之间的完整笛卡尔连接,然后是区域中的所有行。

您可能希望在某些区域附加某些内容。和...接触的东西......好吧,我不知道你的架构是什么样的。

尝试在开头粘贴“EXPLAIN”以获取有关正在发生的事情的信息。

答案 2 :(得分:3)

可能你错过了联接。加入这个表就是这样的。

SELECT DISTINCT p.* 
  FROM points p
  JOIN areas a p ON  a.FkPoint = p.id
  JOIN contacts c ON c.FkArea = a.id
 WHERE (    p.latitude > 43.6511659465 
        AND p.latitude < 43.6711659465 
        AND p.longitude > -79.4677941889 
        AND p.longitude < -79.4477941889) 
   AND p.resource_type = 'Contact' 
   AND c.user_id = 6

要获得更好的坐标索引,请使用四叉树 R-Tree 索引实现。

如果您故意不错过联接,请尝试这样的子查询。

select DISTINCT thePoints.*
(   
    SELECT DISTINCT p.* 
    FROM points p
    WHERE (     p.latitude > 43.6511659465 
            AND p.latitude < 43.6711659465 
            AND p.longitude > -79.4677941889 
            AND p.longitude < -79.4477941889) 
    AND p.resource_type = 'Contact' 
) as thePoints
, areas, contacts
WHERE  c.user_id = 6

答案 3 :(得分:0)

您需要rtree索引并使用@运算符,普通索引将不起作用。

R树 http://www.postgresql.org/docs/8.1/static/indexes-types.html

@运营商 http://www.postgresql.org/docs/8.1/static/functions-geometry.html