Почему этот запрос postgresql такой медленный? - PullRequest
1 голос
/ 08 июня 2010

Я не эксперт по базам данных, но у меня достаточно знаний, чтобы попасть в неприятности, как в данном случае. Этот запрос

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

очень медленно. Таблица точек содержит менее 2000 записей, но выполнение занимает около 8 секунд. Есть указатели на столбцы широты и долготы. Удаление предложения, содержащего resource_type и user_id, не имеет значения.

Поля широты и долготы оба отформатированы как числа (15,10) - мне нужна точность для некоторых вычислений.

Есть много, много других запросов в этом проекте, где сравниваются точки, но нет проблем со временем выполнения. Что происходит?

Ответы [ 4 ]

11 голосов
/ 08 июня 2010

Вы забыли что-то из своего фактического запроса? В трех таблицах отсутствует соединение ANSI-89, что дает вам декартово произведение, но только вытаскивает записи POINTS.

5 голосов
/ 08 июня 2010

Вы объединяете три таблицы, p, a и c, но вы не указываете, как соединить их вместе.Вы получаете полное декартово соединение между всеми строками во всех таблицах, которые соответствуют критериям, а затем по всем областям.

Возможно, вы хотите прикрепить что-то в точках к чему-то в областях.И что-то в контакте с ... ну, я не знаю, как выглядит ваша схема.

Попробуйте вставить "EXPLAIN" в начале для получения информации о том, что происходит.

3 голосов
/ 08 июня 2010

Возможно, вам не хватает соединений. Присоединение к столу будет примерно таким.

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

Для улучшения индексов по координатам используйте Quadtree или 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
0 голосов
/ 08 июня 2010

Вам нужен индекс rtree и оператор @, нормальный индекс не будет работать.

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

@ оператор http://www.postgresql.org/docs/8.1/static/functions-geometry.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...