对于我的硕士论文,我正在分析几种可能对移动服务提供商有用的算法(测试数据集基于移动音乐学校),以寻找一名新学生的最佳老师,以该老师的现有学生为基地考虑在内。
所附代码为简单的KNN(k最近邻)搜索提供了正确的结果,避免了重复。
由于“ DISTINCT ON”要求将st.teacher_id包含在ORDER BY子句中,因此不使用我在几何列“ address_transform”上具有的R-Tree-Index。一旦表的大小变大(学生表为10万行),几何形状变得更复杂等,这将导致非常糟糕的性能。
有什么想法如何重写函数以便使用索引?
CREATE OR REPLACE FUNCTION thesis_knn_distinct (q_neighbors_no integer, q_latitude numeric, q_longitude numeric, q_instrument text, q_student_table character varying)
RETURNS TABLE (
student_id TEXT,
teacher_id TEXT,
distance DOUBLE PRECISION,
instrument TEXT[]
)
AS $$
DECLARE
location_txt varchar(50) := 'SRID=4326;POINT('||q_longitude||' '||q_latitude||')';
teacher_table varchar(25);
BEGIN
IF q_student_table LIKE 'student_hesse%' THEN
teacher_table = 'teacher_synth_large';
ELSIF [...]
END IF;
RETURN QUERY EXECUTE 'WITH teacher_filter AS (
SELECT DISTINCT ON (st.teacher_id) st.id, st.teacher_id, ST_DistanceSphere(address_box, $2::geometry) AS distance, te.instrument
FROM '|| q_student_table::regclass ||' st INNER JOIN '|| teacher_table::regclass ||' te
ON st.teacher_id = te.id
WHERE te.instrument @> ARRAY[$1]::text[]
ORDER BY st.teacher_id, st.address_transform <-> ST_Transform($2::geometry,3857)
)
SELECT * FROM teacher_filter
ORDER BY distance
LIMIT $3;'
USING q_instrument, location_txt, q_neighbors_no;
END; $$
LANGUAGE 'plpgsql';
注释:
我正在使用动态查询,因为我正在测试多个真实/合成数据表(索引,非索引,集群等)
我知道可以设置诸如enable_seqscan这样的配置参数,但这并不是解决我的问题的永久方法
作为替代方案,我已经实现了一个(相当快的)变体,其中我通过简单的KNN预选了多个所需的邻居,然后在第二步中删除了重复项。对于纯与距离相关的方法,这行之有效,但如果在随后的步骤中也考虑了除距离以外的其他参数,则预选不一定包含最佳匹配。
我正在使用postgres 10.4,postgis 2.4.4