我的应用程序从不同来源获取 AVL 数据并将其合并到池表中。
然后我有一个函数map.get_near_link(sq.X, sq.Y, sq.AZIMUTH)
来计算该池中每个汽车位置的最近链接。
CREATE TYPE map.get_near_link AS
(link_id integer,
distance integer, -- distance to the link
sentido integer, -- use azimuth to know what direction of link is traveling
geom geometry(4)); -- the link geometry
目前我收到大约400 avl的分钟,而计算所有这些的near_link
的过程需要10-30秒。所以理论上我可以毫无问题地处理所有记录。但如果源输入增加到+ 800 avl / min,我将无法处理所有数据。
那么我应该采取什么措施让我的流程处理未来数据输入大小的增加。
这是我目前的流程。我设定的工作每分钟都要运行一次。
-- new records doesnt have near_link
SELECT MAX(avl_id) INTO int_pending
FROM avl_db.avl_pool
WHERE near_link IS NULL;
-- loop while the pool isnt empty
WHILE int_pending > 0 LOOP
--udpate take around 10-30 sec
UPDATE avl_db.avl_pool a
SET near_link = map.get_near_link(sq.X, sq.Y, sq.AZIMUTH)
FROM (
-- this select take ~100 ms
SELECT avl_id, x, y, azimuth
FROM avl_db.avl_pool
WHERE near_link IS NULL
ORDER BY avl_id
LIMIT 400 -- I choose 400 after some testing,
-- so doesnt lock the table for too long.
) sq
WHERE a.avl_id = sq.avl_id;
-- check if pool is empty
SELECT MAX(avl_id) INTO int_pending
FROM avl_db.avl_pool
WHERE near_link IS NULL;
END LOOP;
仅供参考:
avl_pool表
CREATE TABLE avl_db.avl_pool
(
avl_id bigserial NOT NULL,
car_id bigint,
hora timestamp without time zone,
x numeric(10,6),
y numeric(10,6),
azimuth integer,
speed numeric(10,3),
near_link map.get_near_link,
CONSTRAINT avl_pool_pkey PRIMARY KEY (avl_id)
);
这是 map.get_near_link
功能。我努力工作以使其更有效率,但如果必须再次工作以减少时间可以接受建议。
CREATE OR REPLACE FUNCTION map.get_near_link(
x numeric, y numeric, azim numeric)
RETURNS map.get_near_link AS
$BODY$
DECLARE
strPoint text;
sRow map.get_near_link;
BEGIN
strPoint = 'POINT('|| X || ' ' || Y || ')';
with index_query as (
SELECT Link_ID, azimuth,
TRUNC(ST_Distance(ST_GeomFromText(strPoint,4326), geom )*100000)::integer as distance,
sentido, geom
FROM map.vzla_seg S
WHERE
abs(Azim - S.azimuth) < 30 OR
abs(Azim - S.azimuth) > 330
ORDER BY
geom <-> ST_GeomFromText(strPoint, 4326)
LIMIT 101
)
SELECT i.Link_ID, i.Distance, i.Sentido, v.geom into sRow
FROM
index_query i inner join
map.vzla_rto v ON i.link_id = v.link_id
ORDER BY
distance limit 1;
if sRow.distance > 50 then
sRow.link_id = -1;
end if;
RETURN sRow;
END;
答案 0 :(得分:0)
abs(Azim - S.azimuth) < 30
的where子句不能使用S.azimuth
上的任何索引。每个SELECT都将导致全表扫描。
如果在执行SELECT查询之前计算了有效方位角范围(或范围),则可能会出现azimuth BETWEEN low AND high
之类的条件。与azimuth
上的索引一起使用可以加快查询速度。