2015-07-17 2 views
2

Я пытаюсь выяснить, как сократить время для этого запроса. Кто-то рассказал мне о EXPLAIN ANALYZE, но я не знаю, как интерпретировать результаты и какие исправления сделать. Какие-либо предложения? Обратите внимание, что я использую базу данных третьей стороны (cartoDB), поэтому я не думаю, что у меня есть возможность создавать индексы.Улучшение производительности сложного запроса PostgreSQL

Вот запрос. Эти две таблицы составляют около 40 строк и около 32 000 строк.

EXPLAIN ANALYZE SELECT 
    id, identifier, 
    CASE 
    WHEN dist < 8046. THEN 1 
    WHEN dist < 16093. THEN 2 
    WHEN dist < 40233. THEN 3 
WHEN dist < 80467. THEN 4 
WHEN dist < 160934. THEN 5 
    ELSE 6 
    END AS grp, 
    count(*) 
FROM (
    SELECT s.id, s.identifier, ST_Distance_Sphere(s.the_geom, c.the_geom) AS dist 
    FROM full_data_for_testing_deid_2 c, demo_locations_table s) AS loc_dist 
GROUP BY 1, 2, 3 
ORDER BY 1, 2, 3 

Вот ответ на EXECUTE ANALYZE:

{ 
    "fields" : { 
    "QUERY PLAN" : { 
     "type" : "string" 
    } 
    }, 
    "rows" : [ 
    { 
     "QUERY PLAN" : "GroupAggregate (cost=373146.40..651612.12 rows=1058805 width=128) (actual time=34120.054..37536.893 rows=197 loops=1)" 
    }, 
    { 
     "QUERY PLAN" : " -> Sort (cost=373146.40..373675.81 rows=1058805 width=128) (actual time=34120.000..36504.439 rows=1058805 loops=1)" 
    }, 
    { 
     "QUERY PLAN" : "  Sort Key: s.id, s.identifier, (CASE WHEN (_st_distance(geography(s.the_geom), geography(c.the_geom), 0::double precision, false) < 8046::double precision) THEN 1 WHEN (_st_distance(geography(s.the_geom), geography(c.the_geom), 0::double precision, false) < 16093::double precision) THEN 2 WHEN (_st_distance(geography(s.the_geom), geography(c.the_geom), 0::double precision, false) < 40233::double precision) THEN 3 WHEN (_st_distance(geography(s.the_geom), geography(c.the_geom), 0::double precision, false) < 80467::double precision) THEN 4 WHEN (_st_distance(geography(s.the_geom), geography(c.the_geom), 0::double precision, false) < 160934::double precision) THEN 5 ELSE 6 END)" 
    }, 
    { 
     "QUERY PLAN" : "  Sort Method: external merge Disk: 35200kB" 
    }, 
    { 
     "QUERY PLAN" : "  -> Nested Loop (cost=0.00..283194.48 rows=1058805 width=128) (actual time=0.688..13487.097 rows=1058805 loops=1)" 
    }, 
    { 
     "QUERY PLAN" : "    -> Seq Scan on full_data_for_testing_deid_2 c (cost=0.00..6845.26 rows=32085 width=32) (actual time=0.006..130.054 rows=32085 loops=1)" 
    }, 
    { 
     "QUERY PLAN" : "    -> Materialize (cost=0.00..1.13 rows=33 width=96) (actual time=0.001..0.028 rows=33 loops=32085)" 
    }, 
    { 
     "QUERY PLAN" : "     -> Seq Scan on demo_locations_table s (cost=0.00..1.10 rows=33 width=96) (actual time=0.003..0.034 rows=33 loops=1)" 
    }, 
    { 
     "QUERY PLAN" : "Total runtime: 37569.205 ms" 
    } 
    ], 
    "time" : 37.574, 
    "total_rows" : 9 
} 
+0

Что замедляет ваш запрос, скорее всего, является внутренним оператором select. Не можете ли вы переработать свой запрос, чтобы избежать его использования? – Osuwariboy

+0

Я довольно новичок в PostgreSQL и mySQL, так что я не совсем уверен, как бы я это сделал. – jonmrich

+0

Я не уверен, какие индексы находятся на столе в настоящее время. Я не знаю, добавляет ли cartodb (где эта служба размещается) индексы или нет. – jonmrich

ответ

0

Проблема заключается в декартовой продукте здесь: ВЫБРАТЬ s.id, s.identifier, ST_Distance_Sphere (s.the_geom, c.the_geom) AS dist FROM full_data_for_testing_deid_2 c, demo_locations_table s

следующий по вложенному циклу. Я не думаю, что вы хотели сделать декартову здесь. вы можете легко отрезать некоторые ненужные контуры более конкретным JOIN ON. Расстояние между двумя точками является коммутативной функцией. Итак, просто добавьте к нему следующее условие: c.pk> s.pk в зависимости от ваших потребностей (нет информации о дизайне схемы)