File: temporal_knn.sql

package info (click to toggle)
postgis 2.3.1%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 58,660 kB
  • ctags: 10,181
  • sloc: ansic: 132,858; sql: 131,148; xml: 46,460; sh: 4,832; perl: 4,476; makefile: 2,749; python: 1,198; yacc: 442; lex: 131
file content (75 lines) | stat: -rw-r--r-- 2,074 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
CREATE OR REPLACE FUNCTION qnodes(q text) RETURNS text
LANGUAGE 'plpgsql' AS
$$
DECLARE
  exp TEXT;
  mat TEXT[];
  ret TEXT[];
BEGIN
  --RAISE NOTICE 'Q: %', q;
  FOR exp IN EXECUTE 'EXPLAIN ' || q
  LOOP
    --RAISE NOTICE 'EXP: %', exp;
    mat := regexp_matches(exp, ' *(?:-> *)?(.*Scan)');
    --RAISE NOTICE 'MAT: %', mat;
    IF mat IS NOT NULL THEN
      ret := array_append(ret, mat[1]);
    END IF;
    --RAISE NOTICE 'RET: %', ret;
  END LOOP;
  RETURN array_to_string(ret,',');
END;
$$;

-- create table
CREATE TABLE knn_cpa AS
WITH points AS (
  SELECT t,
         ST_MakePoint(x-t,x+t) p
  FROM generate_series(0,1000,5) t -- trajectories
      ,generate_series(-100,100,10) x
)
SELECT t, ST_AddMeasure(
  CASE WHEN t%2 = 0 THEN ST_Reverse(ST_MakeLine(p))
       ELSE ST_MakeLine(p) END,
  10, 20) tr
FROM points GROUP BY t;
--ALTER TABLE knn_cpa ADD PRIMARY KEY(t);

\set qt 'ST_AddMeasure(ST_MakeLine(ST_MakePointM(-260,380,0),ST_MakePointM(-360,540,0)),10,20)'

SELECT '|=| no idx', qnodes('select * from knn_cpa ORDER BY tr |=| ' || quote_literal(:qt ::text) || ' LIMIT 1');
CREATE TABLE knn_cpa_no_index AS
SELECT row_number() over () n, t, d FROM (
  SELECT t,
  ST_DistanceCPA(tr,:qt) d
  FROM knn_cpa ORDER BY tr |=| :qt LIMIT 5
) foo;

CREATE INDEX on knn_cpa USING gist (tr gist_geometry_ops_nd);
ANALYZE knn_cpa;
set enable_seqscan to off;

SELECT '|=| idx', qnodes('select * from knn_cpa ORDER BY tr |=| ' || quote_literal(:qt ::text) || ' LIMIT 1');
CREATE TABLE knn_cpa_index AS
SELECT row_number() over () n, t, d FROM (
  SELECT t, ST_DistanceCPA(tr,:qt) d
  FROM knn_cpa ORDER BY tr |=| :qt LIMIT 5
) foo;

--SELECT * FROM knn_cpa_no_index;
--SELECT * FROM knn_cpa_index;

SELECT a.n,
  CASE WHEN a.t = b.t THEN a.t||'' ELSE a.t || ' vs ' || b.t END closest,
  CASE WHEN a.d = b.d THEN 'dist:' || a.d::numeric(10,2) ELSE 'diff:' || (a.d - b.d) END dist
FROM knn_cpa_no_index a, knn_cpa_index b
WHERE a.n = b.n
ORDER BY a.n;

-- Cleanup

DROP FUNCTION qnodes(text);
DROP TABLE knn_cpa;
DROP TABLE knn_cpa_no_index;
DROP TABLE knn_cpa_index;