2010-06-08 2 views
1

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

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). Для некоторых вычислений мне нужна точность.

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

+0

Пожалуйста ВЫВЕШУ EXPLAIN. Различие часто является проблемой производительности. Кроме того, убедитесь, что широта и долгота индексируются. –

ответ

11

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

+2

Не только это, но 'AND c.user_id = 6' ничего не делает, так как никаких результатов от' contacts' не возвращаются. – VeeArr

+0

, но когда сравнения проводятся только между точками и числовыми значениями long & lat, изменение скорости не происходит. Там нет возможности присоединиться, нет? –

+0

@ user315975: Я не знаю ваши данные, но не включаю таблицы, если они служат абсолютно никакой цели. Все еще нужно знать, как отношения «POINTS» и «КОНТАКТЫ» ... –

5

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

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

Попытайтесь вначале попробовать «ОБЪЯСНЕНИЕ» для получения информации о том, что происходит.

+0

Действительно. У вас может быть только 2000 записей в очках, но если у вас 2000 в областях и 2000 в контактах, вы создаете 2000 * 2000 * 2000 = 8 миллиардов строк, а затем сортируете их в разные. – Cowan

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 
0

Вам нужен 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

+0

Индексы R-дерева не существуют 8.3+. – rfusca

+0

Ну, индексы GiST (которые, я думаю, используют R-деревья для типов геометрий) – araqnid

Смежные вопросы