如何加快查询速度?

Posted

技术标签:

【中文标题】如何加快查询速度?【英文标题】:How i can speed up query? 【发布时间】:2016-06-30 11:42:04 【问题描述】:

查询:

with bus_points AS (
 select osm_id, way from opengeo.ru_psk_point where public_transport='stop_position' and tags -> 'bus' = 'yes'
 )
 select 
 id_start,start_way,dist_start,id_end,end_way,dist_end
 ,(dist_start+dist_end) as sum_dist 
 from 
 (select osm_id as id_start, way as start_way, ST_Distance_Spheroid(ST_Transform(way,4326), ST_GeomFromText('POINT(28.2789393 57.8155523)',4326), 'SPHEROID["WGS 84",6378137,298.257223563]') as dist_start from bus_points order by dist_start) t1,
 (select osm_id as id_end, way as end_way, ST_Distance_Spheroid(ST_Transform(way,4326), ST_GeomFromText('POINT(28.2951125 57.8141805)',4326), 'SPHEROID["WGS 84",6378137,298.257223563]') as dist_end from bus_points order by dist_end) t2,
 opengeo.ru_psk_rels rels 
 where array[id_start,id_end]<@rels.parts 
 and array['route','ref']<@rels.tags 
 and bus_idx_rels_parts(rels.id,id_start)<bus_idx_rels_parts(rels.id,id_end) 
 order by sum_dist limit 1;

分析:

"Limit  (cost=1606.91..1606.91 rows=1 width=96) (actual time=4396.739..4396.745 rows=1 loops=1)"
"  CTE bus_points"
"    ->  Seq Scan on ru_psk_point  (cost=0.00..1568.94 rows=1 width=136) (actual time=0.066..17.067 rows=181 loops=1)"
"          Filter: ((public_transport = 'stop_position'::text) AND ((tags -> 'bus'::text) = 'yes'::text))"
"          Rows Removed by Filter: 24330"
"  ->  Sort  (cost=37.97..37.97 rows=1 width=96) (actual time=4396.710..4396.710 rows=1 loops=1)"
"        Sort Key: (((st_distance_spheroid(st_transform(bus_points.way, 4326), '0101000020E6100000B311E39068473C40BB568C0464E84C40'::geometry, 'SPHEROID("WGS 84",6378137,298.257223562997)'::spheroid)) + (st_distance_spheroid(st_transform(bus_points.way, 4326), '0101000020E61000000B24287E8C4B3C403D450E1137E84C40'::geometry, 'SPHEROID("WGS 84",6378137,298.257223562997)'::spheroid))))"
"        Sort Method: top-N heapsort  Memory: 17kB"
"        ->  Nested Loop  (cost=33.39..37.96 rows=1 width=96) (actual time=40.099..4356.620 rows=4731 loops=1)"
"              ->  Nested Loop  (cost=0.57..0.61 rows=1 width=96) (actual time=32.312..651.802 rows=32761 loops=1)"
"                    ->  Sort  (cost=0.28..0.29 rows=1 width=40) (actual time=25.935..27.065 rows=181 loops=1)"
"                          Sort Key: (st_distance_spheroid(st_transform(bus_points.way, 4326), '0101000020E6100000B311E39068473C40BB568C0464E84C40'::geometry, 'SPHEROID("WGS 84",6378137,298.257223562997)'::spheroid))"
"                          Sort Method: quicksort  Memory: 29kB"
"                          ->  CTE Scan on bus_points  (cost=0.00..0.27 rows=1 width=40) (actual time=2.071..24.295 rows=181 loops=1)"
"                    ->  Sort  (cost=0.28..0.29 rows=1 width=40) (actual time=0.041..1.184 rows=181 loops=181)"
"                          Sort Key: (st_distance_spheroid(st_transform(bus_points.way, 4326), '0101000020E61000000B24287E8C4B3C403D450E1137E84C40'::geometry, 'SPHEROID("WGS 84",6378137,298.257223562997)'::spheroid))"
"                          Sort Method: quicksort  Memory: 29kB"
"                          ->  CTE Scan on bus_points  (cost=0.00..0.27 rows=1 width=40) (actual time=1.709..4.828 rows=181 loops=1)"
"              ->  Bitmap Heap Scan on ru_psk_rels rels  (cost=32.82..37.34 rows=1 width=86) (actual time=0.092..0.096 rows=0 loops=32761)"
"                    Recheck Cond: ((ARRAY[bus_points.osm_id, bus_points.osm_id] <@ parts) AND ('route,ref'::text[] <@ tags))"
"                    Filter: (bus_idx_rels_parts(id, bus_points.osm_id) < bus_idx_rels_parts(id, bus_points.osm_id))"
"                    Rows Removed by Filter: 0"
"                    ->  BitmapAnd  (cost=32.82..32.82 rows=1 width=0) (actual time=0.067..0.067 rows=0 loops=32761)"
"                          ->  Bitmap Index Scan on idx_ru_psk_rels_gin_parts  (cost=0.00..12.23 rows=31 width=0) (actual time=0.017..0.017 rows=0 loops=32761)"
"                                Index Cond: (ARRAY[bus_points.osm_id, bus_points.osm_id] <@ parts)"
"                          ->  Bitmap Index Scan on idx_ru_psk_rels_gin_tags  (cost=0.00..20.33 rows=44 width=0) (actual time=0.197..0.197 rows=499 loops=5735)"
"                                Index Cond: ('route,ref'::text[] <@ tags)"
"Total runtime: 4397.374 ms"

我只需要具有最小 SUM_DIST 的一行。

更多

CREATE OR REPLACE FUNCTION bus_idx_rels_parts(IN bigint, IN bigint, OUT idx integer)
RETURNS integer AS
' SELECT idx from opengeo.ru_psk_rels_parts_idx where id=$1 and unnest=$2 '
LANGUAGE sql VOLATILE
COST 100;

和 ORDER BY dist_* 加快时间。

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

【问题讨论】:

这看起来像是一个调试帮助请求(这里不是主题),而不是一个合适的问题。 【参考方案1】:

对于初学者,您可能需要opengeo.ru_psk_point 中的索引。这将取决于您的查询的性质。如果您总是查询与特定 public_transport 相关的标签,则使用组合 GIN 索引:

CREATE INDEX ON opengeo.ru_psk_point USING GIN (public_transport, tags);

如果public_transport 的每种类型只有几个标签,那么只有该字段上的普通索引:

CREATE INDEX ON opengeo.ru_psk_point (public_transport);

如果您有很多不同的标签,您经常查询但不一定与特定的 public_transport 相关,那么tags 上的简单 GIN 索引:

CREATE INDEX ON opengeo.ru_psk_point USING GIN (tags);


更新

您在子查询中有 ORDER BY,是否排序对子查询没有影响 删除子查询中的 ORDER BY 子句 您正在执行函数 bus_idx_rels_parts(a,b) 的 2 x 4,731 次 看看是否有任何毫无意义的比较,或者这些函数的代码是否可以以 PostgreSQL 可以优化连接的方式移植到查询中

【讨论】:

这无济于事。节省时间。 @user15445 添加了更多注释

以上是关于如何加快查询速度?的主要内容,如果未能解决你的问题,请参考以下文章

如何加快查询速度?

如何加快查询速度

如何在 Azure 表存储中使用 partitionkey 加快查询速度

如何使用多个 INNER JOIN 加快查询速度

带有排序的 MongoDB 范围查询 - 如何加快速度?

如何通过 IP 地址查询加快国家检测速度?