3

对于我的硕士论文,我正在分析几种可能对移动服务提供商有用的算法(测试数据集基于移动音乐学校),以便在考虑教师现有学生的位置的情况下为新学生找到最佳教师。

所附代码为避免重复的简单 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

4

0 回答 0