对于我的硕士论文,我正在分析几种可能对移动服务提供商有用的算法(测试数据集基于移动音乐学校),以便在考虑教师现有学生的位置的情况下为新学生找到最佳教师。
所附代码为避免重复的简单 KNN(k-最近邻)搜索提供了正确结果。
由于“DISTINCT ON”要求 st.teacher_id 包含在 ORDER BY 子句中,因此不使用我在几何列“address_transform”上的 R-Tree-Index。一旦表大小变大(学生表为 100k 行),几何变得更复杂等,这会导致性能非常差。
任何想法如何重写函数以便使用索引?
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