我在PostgreSQL 9.6.6上运行此查询。该查询由Tableau自动生成。有点慢,表上有一些索引,想知道是否可以进一步改进?
EXPLAIN ANALYZE
SELECT COUNT(DISTINCT (CASE WHEN (("Custom SQL Query"."yearmonth" >= CAST(((CAST(10 AS TEXT) || '/1/') || CAST(2017 AS TEXT)) AS DATE)) AND ("Custom SQL Query"."yearmonth" <= CAST(((CAST(7 AS TEXT) || '/1/') || CAST(2018 AS TEXT)) AS DATE))) THEN "Custom SQL Query"."retainedstudent" WHEN NOT (("Custom SQL Query"."yearmonth" >= CAST(((CAST(10 AS TEXT) || '/1/') || CAST(2017 AS TEXT)) AS DATE)) AND ("Custom SQL Query"."yearmonth" <= CAST(((CAST(7 AS TEXT) || '/1/') || CAST(2018 AS TEXT)) AS DATE))) THEN NULL ELSE NULL END)) AS "TEMP(Calculation_2527926833913348124)(4191847360)(0)",
COUNT(DISTINCT (CASE WHEN (("Custom SQL Query"."yearmonth" >= (CAST(((CAST(10 AS TEXT) || '/1/') || CAST(2017 AS TEXT)) AS DATE) + -12 * INTERVAL '1 MONTH')) AND ("Custom SQL Query"."yearmonth" <= (CAST(((CAST(7 AS TEXT) || '/1/') || CAST(2018 AS TEXT)) AS DATE) + -12 * INTERVAL '1 MONTH'))) THEN "Custom SQL Query"."retainedstudent" WHEN NOT (("Custom SQL Query"."yearmonth" >= (CAST(((CAST(10 AS TEXT) || '/1/') || CAST(2017 AS TEXT)) AS DATE) + -12 * INTERVAL '1 MONTH')) AND ("Custom SQL Query"."yearmonth" <= (CAST(((CAST(7 AS TEXT) || '/1/') || CAST(2018 AS TEXT)) AS DATE) + -12 * INTERVAL '1 MONTH'))) THEN NULL ELSE NULL END)) AS "TEMP(retainedstudent pre year (copy 2))(2234470420)(0)",
COUNT(DISTINCT (CASE WHEN (("Custom SQL Query"."date" >= (CAST(((CAST(10 AS TEXT) || '/1/') || CAST(2017 AS TEXT)) AS DATE) + -12 * INTERVAL '1 MONTH')) AND ("Custom SQL Query"."date" <= (CURRENT_TIMESTAMP + -12 * INTERVAL '1 MONTH'))) THEN "Custom SQL Query"."retainedstudent" WHEN NOT (("Custom SQL Query"."date" >= (CAST(((CAST(10 AS TEXT) || '/1/') || CAST(2017 AS TEXT)) AS DATE) + -12 * INTERVAL '1 MONTH')) AND ("Custom SQL Query"."date" <= (CURRENT_TIMESTAMP + -12 * INTERVAL '1 MONTH'))) THEN NULL ELSE NULL END)) AS "TEMP(retainedstudent pre year (copy 2))(4101084651)(0)",
MIN(CURRENT_TIMESTAMP) AS "TEMP(retainedstudent pre year (copy 2))(911232254)(0)",
"Custom SQL Query"."business_unit" AS "business_unit",
"Custom SQL Query"."center_name" AS "center_name",
"Custom SQL Query"."city" AS "city"
FROM (
SELECT
center_name
,student1.Center_Code
,business_unit
,city
,program_name
,program_code
,Program_group
,production_type
,yearmonth
,date
,newstudent
,retainedstudent
,user_center_mapping.user_name
, iscentertransfer
,region_level_1
, region_level_2
FROM dmt_student.student1
join dmt_security.user_center_mapping on student1.Center_Code = user_center_mapping.center_code
) "Custom SQL Query"
WHERE (((("Custom SQL Query"."business_unit" = 'Indonesia Franchise') AND (("Custom SQL Query"."city" >= 'Bali') AND ("Custom SQL Query"."city" <= 'Yogyakarta'))) AND (("Custom SQL Query"."user_name" = 'arie.trisna') AND (("Custom SQL Query"."iscentertransfer" = 'false') AND (("Custom SQL Query"."production_type" IS NULL) OR (("Custom SQL Query"."production_type" >= 'Book') AND ("Custom SQL Query"."production_type" <= 'Self-study Online')))))) AND ((("Custom SQL Query"."program_group" >= 'Elective') AND (("Custom SQL Query"."program_group" <= 'General') AND (("Custom SQL Query"."program_name" IS NULL) OR (("Custom SQL Query"."program_name" >= 'Business English') AND ("Custom SQL Query"."program_name" <= 'Writer''s Guild'))))) AND (("Custom SQL Query"."region_level_1" IN ('Region 1', 'Region 2')) AND (("Custom SQL Query"."region_level_2" >= 'Bandung Group') AND ("Custom SQL Query"."region_level_2" <= 'Yusmansyah Group')))))
GROUP BY 5,
6,
7
dmt_student.student1上的索引
CREATE INDEX idx_dmt_student_student1 ON dmt_student.student1 USING btree (yearmonth, center_code, business_unit, city, center_name);
dmt_security.user_center_mapping上的索引
CREATE INDEX idx_center_code ON dmt_security.user_center_mapping USING btree (center_code);
CREATE INDEX idx_dmt_security_user_center_mapping_user_name ON dmt_security.user_center_mapping USING btree (user_name, center_code);
这是查询计划
QUERY PLAN
GroupAggregate (cost=328171.81..328285.11 rows=824 width=61) (actual time=10629.395..13630.069 rows=59 loops=1)
Group Key: student1.business_unit, student1.center_name, student1.city
-> Sort (cost=328171.81..328173.87 rows=824 width=54) (actual time=10447.879..10929.413 rows=631215 loops=1)
Sort Key: student1.center_name, student1.city
Sort Method: external merge Disk: 45904kB
-> Hash Join (cost=4.41..328131.90 rows=824 width=54) (actual time=1.046..9212.885 rows=631215 loops=1)
Hash Cond: ((student1.center_code)::text = (user_center_mapping.center_code)::text)
-> Seq Scan on student1 (cost=0.00..327588.35 rows=70787 width=58) (actual time=0.045..8791.642 rows=631215 loops=1)
Filter: (((city)::text >= 'Bali'::text) AND ((city)::text <= 'Yogyakarta'::text) AND ((program_group)::text >= 'Elective'::text) AND ((program_group)::text <= 'General'::text) AND ((region_level_1)::text = ANY ('{"Region 1","Region 2"}'::text[])) AND ((region_level_2)::text >= 'Bandung Group'::text) AND ((region_level_2)::text <= 'Yusmansyah Group'::text) AND ((business_unit)::text = 'Indonesia Franchise'::text) AND ((iscentertransfer)::text = 'false'::text) AND ((production_type IS NULL) OR (((production_type)::text >= 'Book'::text) AND ((production_type)::text <= 'Self-study Online'::text))) AND ((program_name IS NULL) OR (((program_name)::text >= 'Business English'::text) AND ((program_name)::text <= 'Writer''s Guild'::text))))
Rows Removed by Filter: 4851405
-> Hash (cost=4.36..4.36 rows=4 width=4) (actual time=0.988..0.988 rows=80 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 11kB
-> Index Only Scan using idx_dmt_security_user_center_mapping_user_name on user_center_mapping (cost=0.29..4.36 rows=4 width=4) (actual time=0.927..0.956 rows=80 loops=1)
Index Cond: (user_name = 'arie.trisna'::text)
Heap Fetches: 0
Planning time: 5.796 ms
Execution time: 13636.158 ms