Jua*_*eza 9 c# sql postgresql performance multithreading
我有一张桌子avl_pool
,我有一个功能,可以在地图上找到离该(x, y)
位置最近的链接.
该选择的性能非常线性,该功能需要~8 ms才能执行.因此,计算此行选择1000行需要8秒.或者,正如我在此示例中所示,20.000行需要162秒.
SELECT avl_id, x, y, azimuth, map.get_near_link(X, Y, AZIMUTH)
FROM avl_db.avl_pool
WHERE avl_id between 1 AND 20000
"Index Scan using avl_pool_pkey on avl_pool (cost=0.43..11524.76 rows=19143 width=28) (actual time=8.793..162805.384 rows=20000 loops=1)"
" Index Cond: ((avl_id >= 1) AND (avl_id <= 20000))"
" Buffers: shared hit=19879838"
"Planning time: 0.328 ms"
"Execution time: 162812.113 ms"
Run Code Online (Sandbox Code Playgroud)
使用pgAdmin我发现如果同时在分离的窗口上执行一半的范围,执行时间实际上被分成两半.所以看起来服务器可以毫无问题地处理对同一个表/函数的多个请求.
-- windows 1
SELECT avl_id, x, y, azimuth, map.get_near_link(X, Y, AZIMUTH)
FROM avl_db.avl_pool
WHERE avl_id between 1 AND 10000
Total query runtime: 83792 ms.
-- windows 2
SELECT avl_id, x, y, azimuth, map.get_near_link(X, Y, AZIMUTH)
FROM avl_db.avl_pool
WHERE avl_id between 10001 AND 20000
Total query runtime: 84047 ms.
Run Code Online (Sandbox Code Playgroud)
那么我该如何应对这种情况以提高性能呢?
从C#
aproach我想我可以创建多个线程,每个线程发送一部分范围,然后我加入客户端中的所有数据.所以相反,一个查询有20k和162秒,我可以发送10行查询2000行,并在~16秒内完成.当然,在连接中可能存在开销成本,但与160秒相比不应该很大.
或者我应该考虑一个不同的方法,如果只是一个简单的SQL解决方案更好?
@PeterRing我不认为功能代码是相关的,但无论如何这里是.
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 || ')';
RAISE DEBUG 'GetLink strPoint % -- Azim %', strPoint, Azim;
WITH index_query AS (
SELECT --Seg_ID,
Link_ID,
azimuth,
TRUNC(ST_Distance(ST_GeomFromText(strPoint,4326), geom )*100000)::INTEGER AS distance,
sentido,
--ST_AsText(geom),
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;
RAISE DEBUG 'GetLink distance % ', sRow.distance;
IF sRow.distance > 50 THEN
sRow.link_id = -1;
END IF;
RETURN sRow;
END;
$BODY$
LANGUAGE plpgsql IMMUTABLE
COST 100;
ALTER FUNCTION map.get_near_link(NUMERIC, NUMERIC, NUMERIC)
OWNER TO postgres;
Run Code Online (Sandbox Code Playgroud)
我曾经做过这样的事情。效果相对较好。请注意,每个连接一次只能处理一个查询,因此对于查询的每个分区,您必须有一个单独的连接。现在,在 C# 中,您可以使用线程与每个连接进行交互。
但另一种选择是使用异步查询并让单个线程管理和轮询整个连接池(这有时会简化应用程序端的数据操作)。请注意,在这种情况下,您最好确保每个轮询周期后都有一个睡眠或其他屈服点。
进一步请注意,查询速度的加快程度取决于您的磁盘 I/O 子系统和 CPU 并行性。因此,您不能只是抛出更多查询片段并期望加速。
归档时间: |
|
查看次数: |
583 次 |
最近记录: |