加入视图

时间:2015-06-16 08:04:13

标签: performance postgresql join view

我正在使用PostgreSQL 9.4.4

视图V_OpenCourse_WithTC

 SELECT x1.id,
    (x1.data ->> 'subject_id'::text)::bigint AS subject_id,
    x2.data ->> 'program_session'::text AS program_session,
    (x2.data ->> 'semester_id'::text)::bigint AS semester_id,
    (x2.data ->> 'curriculum_id'::text)::bigint AS curriculum_id,
    (x3.data ->> 'major_id'::text)::bigint AS major_id
   FROM open_courses x1
     JOIN trimester_courses x2 ON ((x1.data ->> 'trimester_course_id'::text)::bigint) = x2.id
     JOIN tags x3 ON ((x2.data ->> 'curriculum_id'::text)::bigint) = x3.id AND (x3.data ->> 'type'::text) = 'curriculum'::text
  WHERE x1.is_deleted = false;

从该视图中选择=快速

explain analyze SELECT * FROM V_OpenCourse_WithTC;
                                                               QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------
 Hash Join  (cost=92.89..251.57 rows=18 width=382) (actual time=2.086..9.478 rows=3832 loops=1)
   Hash Cond: (((x1.data ->> 'trimester_course_id'::text))::bigint = x2.id)
   ->  Seq Scan on open_courses x1  (cost=0.00..128.00 rows=3991 width=105) (actual time=0.007..0.815 rows=3991 loops=1)
         Filter: (NOT is_deleted)
         Rows Removed by Filter: 9
   ->  Hash  (cost=92.81..92.81 rows=6 width=285) (actual time=2.067..2.067 rows=1405 loops=1)
         Buckets: 1024  Batches: 1  Memory Usage: 558kB
         ->  Hash Join  (cost=31.16..92.81 rows=6 width=285) (actual time=0.297..1.508 rows=1405 loops=1)
               Hash Cond: (((x2.data ->> 'curriculum_id'::text))::bigint = x3.id)
               ->  Seq Scan on trimester_courses x2  (cost=0.00..51.05 rows=1405 width=131) (actual time=0.003..0.160 rows=1405 loops=1)
               ->  Hash  (cost=31.12..31.12 rows=3 width=162) (actual time=0.287..0.287 rows=101 loops=1)
                     Buckets: 1024  Batches: 1  Memory Usage: 25kB
                     ->  Seq Scan on tags x3  (cost=0.00..31.12 rows=3 width=162) (actual time=0.168..0.264 rows=101 loops=1)
                           Filter: ((data ->> 'type'::text) = 'curriculum'::text)
                           Rows Removed by Filter: 574
 Planning time: 0.226 ms
 Execution time: 9.655 ms
(17 rows)

从主表中选择=快速

explain analyze 
    SELECT id, data->>'open_course_id' oc_id
    FROM student_credits 
    WHERE (data->>'student_id')::BIGINT = '5500'

                                                     QUERY PLAN                                                     
--------------------------------------------------------------------------------------------------------------------
 Seq Scan on student_credits  (cost=0.00..14631.51 rows=910 width=396) (actual time=37.330..71.647 rows=33 loops=1)
   Filter: (((data ->> 'student_id'::text))::bigint = 5500::bigint)
   Rows Removed by Filter: 181979
 Planning time: 0.043 ms
 Execution time: 71.665 ms

1手动连接SELECT,不带view = fast

explain analyze 
SELECT x1.id
FROM student_credits x1
    JOIN course_classes x2
        ON (x1.data->>'course_class_id')::BIGINT = x2.id
    JOIN open_courses x3
        ON (x2.data->>'open_course_id')::BIGINT = x3.id
    JOIN trimester_courses x4
        ON (x3.data->>'trimester_course_id')::BIGINT = x4.id
WHERE (x1.data->>'student_id')::BIGINT = '5500'
        AND x4.data->>'semester_id' = '53'

                                                                     QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------
 Hash Join  (cost=1541.70..16177.81 rows=5 width=8) (actual time=80.254..80.254 rows=0 loops=1)
   Hash Cond: (((x1.data ->> 'course_class_id'::text))::bigint = x2.id)
   ->  Seq Scan on student_credits x1  (cost=0.00..14629.24 rows=910 width=396) (actual time=25.195..72.745 rows=33 loops=1)
         Filter: (((data ->> 'student_id'::text))::bigint = 5500::bigint)
         Rows Removed by Filter: 181979
   ->  Hash  (cost=1541.08..1541.08 rows=50 width=8) (actual time=7.473..7.473 rows=814 loops=1)
         Buckets: 1024  Batches: 1  Memory Usage: 32kB
         ->  Hash Join  (cost=216.61..1541.08 rows=50 width=8) (actual time=2.050..7.372 rows=814 loops=1)
               Hash Cond: (((x2.data ->> 'open_course_id'::text))::bigint = x3.id)
               ->  Seq Scan on course_classes x2  (cost=0.00..1248.55 rows=10055 width=653) (actual time=0.002..0.946 rows=10055 loops=1)
               ->  Hash  (cost=216.36..216.36 rows=20 width=8) (actual time=2.038..2.038 rows=410 loops=1)
                     Buckets: 1024  Batches: 1  Memory Usage: 17kB
                     ->  Hash Join  (cost=58.16..216.36 rows=20 width=8) (actual time=0.463..1.992 rows=410 loops=1)
                           Hash Cond: (((x3.data ->> 'trimester_course_id'::text))::bigint = x4.id)
                           ->  Seq Scan on open_courses x3  (cost=0.00..128.00 rows=4000 width=105) (actual time=0.002..0.315 rows=4000 loops=1)
                           ->  Hash  (cost=58.08..58.08 rows=7 width=8) (actual time=0.447..0.447 rows=142 loops=1)
                                 Buckets: 1024  Batches: 1  Memory Usage: 6kB
                                 ->  Seq Scan on trimester_courses x4  (cost=0.00..58.08 rows=7 width=8) (actual time=0.011..0.431 rows=142 loops=1)
                                       Filter: ((data ->> 'semester_id'::text) = '53'::text)
                                       Rows Removed by Filter: 1263
 Planning time: 0.234 ms
 Execution time: 80.296 ms
(22 rows)

2使用WHERE IN从view = fast

中选择
explain analyze
SELECT x1.id
FROM student_credits x1
WHERE (x1.data->>'student_id')::BIGINT = '5500'
        AND (x1.data->>'open_course_id')::BIGINT IN (
                SELECT id
                FROM V_OpenCourse_WithTC
                WHERE semester_id = '53'
        )

                                                                   QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------
 Nested Loop Semi Join  (cost=65.19..14905.52 rows=455 width=8) (actual time=87.144..87.144 rows=0 loops=1)
   Join Filter: (((x1.data ->> 'open_course_id'::text))::bigint = x1_1.id)
   Rows Removed by Join Filter: 13233
   ->  Seq Scan on student_credits x1  (cost=0.00..14629.24 rows=910 width=396) (actual time=23.892..71.475 rows=33 loops=1)
         Filter: (((data ->> 'student_id'::text))::bigint = 5500::bigint)
         Rows Removed by Filter: 181979
   ->  Materialize  (cost=65.19..255.81 rows=1 width=8) (actual time=0.021..0.420 rows=401 loops=33)
         ->  Nested Loop  (cost=65.19..255.80 rows=1 width=8) (actual time=0.680..13.356 rows=401 loops=1)
               Join Filter: (((x2.data ->> 'curriculum_id'::text))::bigint = x3.id)
               Rows Removed by Join Filter: 40100
               ->  Hash Join  (cost=65.19..223.32 rows=20 width=131) (actual time=0.501..2.150 rows=401 loops=1)
                     Hash Cond: (((x1_1.data ->> 'trimester_course_id'::text))::bigint = x2.id)
                     ->  Seq Scan on open_courses x1_1  (cost=0.00..128.00 rows=3991 width=105) (actual time=0.006..0.580 rows=3991 loops=1)
                           Filter: (NOT is_deleted)
                           Rows Removed by Filter: 9
                     ->  Hash  (cost=65.10..65.10 rows=7 width=131) (actual time=0.481..0.481 rows=142 loops=1)
                           Buckets: 1024  Batches: 1  Memory Usage: 23kB
                           ->  Seq Scan on trimester_courses x2  (cost=0.00..65.10 rows=7 width=131) (actual time=0.009..0.454 rows=142 loops=1)
                                 Filter: (((data ->> 'semester_id'::text))::bigint = 53::bigint)
                                 Rows Removed by Filter: 1263
               ->  Materialize  (cost=0.00..31.14 rows=3 width=8) (actual time=0.000..0.004 rows=101 loops=401)
                     ->  Seq Scan on tags x3  (cost=0.00..31.12 rows=3 width=8) (actual time=0.114..0.208 rows=101 loops=1)
                           Filter: ((data ->> 'type'::text) = 'curriculum'::text)
                           Rows Removed by Filter: 574
 Planning time: 0.320 ms
 Execution time: 87.188 ms
(26 rows)

3选择JOIN来查看=慢

explain analyze
SELECT x1.id
FROM student_credits x1
, V_OpenCourse_WithTC x2
WHERE (x1.data->>'student_id')::BIGINT = '5500'
        AND x2.semester_id = '53'
        AND (x1.data->>'open_course_id')::BIGINT = x2.id

                                                              QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
 Nested Loop  (cost=177.89..14951.55 rows=1 width=8) (actual time=10155.277..10155.277 rows=0 loops=1)
   Join Filter: (((x1_1.data ->> 'trimester_course_id'::text))::bigint = x2.id)
   ->  Nested Loop  (cost=0.00..96.70 rows=1 width=8) (actual time=0.221..5.487 rows=142 loops=1)
         Join Filter: (((x2.data ->> 'curriculum_id'::text))::bigint = x3.id)
         Rows Removed by Join Filter: 14200
         ->  Seq Scan on trimester_courses x2  (cost=0.00..65.10 rows=7 width=131) (actual time=0.013..0.637 rows=142 loops=1)
               Filter: (((data ->> 'semester_id'::text))::bigint = 53::bigint)
               Rows Removed by Filter: 1263
         ->  Materialize  (cost=0.00..31.14 rows=3 width=8) (actual time=0.001..0.006 rows=101 loops=142)
               ->  Seq Scan on tags x3  (cost=0.00..31.12 rows=3 width=8) (actual time=0.146..0.225 rows=101 loops=1)
                     Filter: ((data ->> 'type'::text) = 'curriculum'::text)
                     Rows Removed by Filter: 574
   ->  Hash Join  (cost=177.89..14836.68 rows=908 width=105) (actual time=71.475..71.475 rows=0 loops=142)
         Hash Cond: (((x1.data ->> 'open_course_id'::text))::bigint = x1_1.id)
         ->  Seq Scan on student_credits x1  (cost=0.00..14629.24 rows=910 width=396) (actual time=36.517..71.458 rows=33 loops=142)
               Filter: (((data ->> 'student_id'::text))::bigint = 5500::bigint)
               Rows Removed by Filter: 181979
         ->  Hash  (cost=128.00..128.00 rows=3991 width=105) (actual time=1.428..1.428 rows=3991 loops=1)
               Buckets: 1024  Batches: 1  Memory Usage: 549kB
               ->  Seq Scan on open_courses x1_1  (cost=0.00..128.00 rows=3991 width=105) (actual time=0.005..0.736 rows=3991 loops=1)
                     Filter: (NOT is_deleted)
                     Rows Removed by Filter: 9
 Planning time: 0.309 ms
 Execution time: 10155.321 ms
(24 rows)

4选择JOIN到过滤视图=慢

explain analyze 
SELECT x1.id    
FROM student_credits x1
JOIN (
SELECT * FROM V_OpenCourse_WithTC 
        WHERE semester_id = '53'
     ) x2 
        ON (x1.data->>'open_course_id')::BIGINT = x2.id 
WHERE (x1.data->>'student_id')::BIGINT = '5500'

                                                              QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
 Nested Loop  (cost=177.89..14951.55 rows=1 width=8) (actual time=10229.667..10229.667 rows=0 loops=1)
   Join Filter: (((x1_1.data ->> 'trimester_course_id'::text))::bigint = x2.id)
   ->  Nested Loop  (cost=0.00..96.70 rows=1 width=8) (actual time=0.218..5.623 rows=142 loops=1)
         Join Filter: (((x2.data ->> 'curriculum_id'::text))::bigint = x3.id)
         Rows Removed by Join Filter: 14200
         ->  Seq Scan on trimester_courses x2  (cost=0.00..65.10 rows=7 width=131) (actual time=0.014..0.705 rows=142 loops=1)
               Filter: (((data ->> 'semester_id'::text))::bigint = 53::bigint)
               Rows Removed by Filter: 1263
         ->  Materialize  (cost=0.00..31.14 rows=3 width=8) (actual time=0.001..0.006 rows=101 loops=142)
               ->  Seq Scan on tags x3  (cost=0.00..31.12 rows=3 width=8) (actual time=0.142..0.229 rows=101 loops=1)
                     Filter: ((data ->> 'type'::text) = 'curriculum'::text)
                     Rows Removed by Filter: 574
   ->  Hash Join  (cost=177.89..14836.68 rows=908 width=105) (actual time=71.998..71.998 rows=0 loops=142)
         Hash Cond: (((x1.data ->> 'open_course_id'::text))::bigint = x1_1.id)
         ->  Seq Scan on student_credits x1  (cost=0.00..14629.24 rows=910 width=396) (actual time=36.812..71.981 rows=33 loops=142)
               Filter: (((data ->> 'student_id'::text))::bigint = 5500::bigint)
               Rows Removed by Filter: 181979
         ->  Hash  (cost=128.00..128.00 rows=3991 width=105) (actual time=1.401..1.401 rows=3991 loops=1)
               Buckets: 1024  Batches: 1  Memory Usage: 549kB
               ->  Seq Scan on open_courses x1_1  (cost=0.00..128.00 rows=3991 width=105) (actual time=0.005..0.681 rows=3991 loops=1)
                     Filter: (NOT is_deleted)
                     Rows Removed by Filter: 9
 Planning time: 0.313 ms
 Execution time: 10229.720 ms
(24 rows)

5来自两个过滤的第一个=慢

explain analyze
SELECT x1.id    
FROM ( 
    SELECT id, data->>'open_course_id' oc_id
    FROM student_credits 
    WHERE (data->>'student_id')::BIGINT = '5500'
) x1
JOIN (
    SELECT id FROM V_OpenCourse_WithTC 
        WHERE semester_id = '53'
) x2 ON x1.oc_id::BIGINT = x2.id  

                                                             QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------
 Nested Loop  (cost=177.89..14951.55 rows=1 width=8) (actual time=10251.851..10251.851 rows=0 loops=1)
   Join Filter: (((x1.data ->> 'trimester_course_id'::text))::bigint = x2.id)
   ->  Nested Loop  (cost=0.00..96.70 rows=1 width=8) (actual time=0.222..5.581 rows=142 loops=1)
         Join Filter: (((x2.data ->> 'curriculum_id'::text))::bigint = x3.id)
         Rows Removed by Join Filter: 14200
         ->  Seq Scan on trimester_courses x2  (cost=0.00..65.10 rows=7 width=131) (actual time=0.012..0.678 rows=142 loops=1)
               Filter: (((data ->> 'semester_id'::text))::bigint = 53::bigint)
               Rows Removed by Filter: 1263
         ->  Materialize  (cost=0.00..31.14 rows=3 width=8) (actual time=0.001..0.007 rows=101 loops=142)
               ->  Seq Scan on tags x3  (cost=0.00..31.12 rows=3 width=8) (actual time=0.140..0.227 rows=101 loops=1)
                     Filter: ((data ->> 'type'::text) = 'curriculum'::text)
                     Rows Removed by Filter: 574
   ->  Hash Join  (cost=177.89..14836.68 rows=908 width=105) (actual time=72.154..72.154 rows=0 loops=142)
         Hash Cond: (((student_credits.data ->> 'open_course_id'::text))::bigint = x1.id)
         ->  Seq Scan on student_credits  (cost=0.00..14629.24 rows=910 width=396) (actual time=36.960..72.137 rows=33 loops=142)
               Filter: (((data ->> 'student_id'::text))::bigint = 5500::bigint)
               Rows Removed by Filter: 181979
         ->  Hash  (cost=128.00..128.00 rows=3991 width=105) (actual time=1.406..1.406 rows=3991 loops=1)
               Buckets: 1024  Batches: 1  Memory Usage: 549kB
               ->  Seq Scan on open_courses x1  (cost=0.00..128.00 rows=3991 width=105) (actual time=0.005..0.656 rows=3991 loops=1)
                     Filter: (NOT is_deleted)
                     Rows Removed by Filter: 9
 Planning time: 0.312 ms
 Execution time: 10251.902 ms
(24 rows)

问题是,为什么用视图(3-5)查询JOIN,在这种情况下这么慢?

0 个答案:

没有答案