私のアプリケーションは、さまざまな情報源からのAVLのデータを取得し、プールテーブルにマージします。dbプロセスをスケーラブルにするにはどうすればよいですか?
次に、私はそのプール内のすべての車の位置に最も近いリンクが何であるかを計算するために関数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;
(1)テーブルのDDL +カーディナリティを追加してください。(2)空間インデックスを作成し、それらがオプティマイザで使用されていると仮定できますか? (3)AVLと相対良好フィルタであるリンクとの間に最大の関連距離があると仮定できるか? –
@DuduMarkovitz(1)avl_poolは〜400レコード/分を増やします。私はプールテーブルを非常に頻繁にクリーニングします。 (2)はい、空間インデックスがあり、近くのリンクを見つけるために '<->'を多くスピードします。 (3)はい、私は最も近い100リンクに検索を制限し、 'if sRow.distance> 50 then'(4)ddlを追加しますが、これ以上は表示しません。 x、y、azimuth、near_link –
'ST_GeomFromText()'は何をするのですか?それは2度呼ばれ、あなたはそれのための文字列を構成する必要があります。 XとYを取るために書き直せますか? – Hogan