我有以下查询,需要花费约15-20秒才能运行。
表定义 (
with cte0 as ( SELECT label, date, CASE WHEN Lead(label || date || "number") OVER (PARTITION BY label || date || "number" ORDER BY "label", "date", "number", "time") IS NULL THEN '1'::numeric ELSE '0'::numeric END As "unique" FROM table_data LEFT JOIN table_mapper ON table_mapper."type" = table_data."type" WHERE Date BETWEEN date_trunc('month', current_date - 1) and current_date - 1 ) SELECT 'MTD' as "label", round(sum("unique") / count("unique") *100,1) as "value" FROM cte0 WHERE "date" BETWEEN date_trunc('month', current_date - 1) AND current_date -1 UNION ALL SELECT 'Week' as "label", round(sum("unique") / count("unique") *100,1) as "value" FROM cte0 WHERE "date" BETWEEN date_trunc('week', current_date - 1) AND current_date -1 UNION ALL SELECT 'FTD' as "label", round(sum("unique") / count("unique") *100,1) as "value" FROM cte0 WHERE "date" = current_date -1在表格
table_data
中,我将在date
列上创建索引。
CREATE INDEX ix_cli_date ON table_data USING btree (date);
表定义 (\d table_data
)
Table "public.table_data" Column | Type | Modifiers ------------------+------------------------+----------- date | date | not null number | bigint | not null time | time without time zone | not null end time | time without time zone | not null duration | integer | not null time1 | integer | not null time2 | integer | not null time3 | integer | not null time4 | integer | not null time5 | integer | not null time6 | integer | not null time7 | integer | not null type | text | not null name | text | not null id1 | integer | not null id2 | integer | not null key | integer | not null status | text | not null Indexes: "ix_cli_date" btree (date)
表定义 (\d table_mapper
)
Table "public.table_mapper" Column | Type | Modifiers ------------+------+----------- type | text | not null label | text | not null label2 | text | not null label3 | text | not null label4 | text | not null label5 | text | not null
查询的EXPLAIN ANALYZE解释
结果 (cost=184342.66..230332.86 rows=3 width=64) (实际时间=23377.923..25695.478 行数=3 循环次数=1)" CTE cte0" -> 窗口聚合 (cost=121516.06..156751.65 rows=612793 width=23) (实际时间=14578.000..18985.958 行数=696157 循环次数=1)" -> 排序 (cost=121516.06..123048.04 rows=612793 width=23) (实际时间=14577.975..17084.405 行数=696157 循环次数=1)" 排序关键字: (((table_mapper.label || (table_data.date)::text) || (table_data."number")::text)), table_mapper.label, table_data.date, table_data."number", table_data."time"" 排序方法: 外部归并 磁盘: 39480kB" -> 哈希左连接 (cost=11.96..37474.21 rows=612793 width=23) (实际时间=1.449..3308.718 行数=696157 循环次数=1)" 哈希条件: (table_data."type" = table_mapper."type")" -> 使用ix_cli_date索引扫描的table_data (cost=0.02..29036.36 rows=612793 width=38) (实际时间=0.141..946.648 行数=696157 循环次数=1)" 索引条件: ((date >= date_trunc('month'::text, ((('now'::text)::date - 1))::timestamp with time zone)) AND (date 哈希 (cost=7.53..7.53 rows=353 width=25) (实际时间=1.275..1.275 行数=336 循环次数=1)" 桶: 1024 批处理: 1 内存使用: 15kB" -> 顺序扫描table_mapper (cost=0.00..7.53 rows=353 width=25) (实际时间=0.020..0.589 行数=336 循环次数=1)" -> 追加 (cost=27591.00..73581.21 rows=3 width=64) (实际时间=23377.920..25695.467 行数=3 循环次数=1)" -> 聚合 (cost=27591.00..27591.02 rows=1 width=32) (实际时间=23377.917..23377.918 行数=1 循环次数=1)" -> CTE cte0的扫描 (cost=0.00..27575.68 rows=3064 width=32) (实际时间=14578.052..22335.236 行数=696157 循环次数=1)" 过滤条件: ((date = date_trunc('month'::text, ((('now'::text)::date - 1))::timestamp with time zone)))" -> 聚合 (cost=27591.00..27591.02 rows=1 width=32) (实际时间=1741.509..1741.510 行数=1 循环次数=1)" -> CTE cte0的扫描 (cost=0.00..27575.68 rows=3064 width=32) (实际时间=20.009..1522.352 行数=168261 循环次数=1)" 过滤条件: ((date = date_trunc('week'::text, ((('now'::text)::date - 1))::timestamp with time zone)))" -> 聚合 (cost=18399.11..18399.13 rows=1 width=32) (实际时间=576.029..576.030 行数=1 循环次数=1)" -> CTE cte0的描述:
我正在从
table_data
中获取唯一计数和重复计数,这就是LEAD
帮助我的地方,我给列的最后一个重复值赋值0。假设在一列中有3个
x
。我为前两个x
分别赋值1
,第三个x
赋值为0
。实际上,通过一个
cte
,我正在从表table_data
中取出整行,并使用lead进行一些计算,在定义的日期范围内将每行的1
和0
值根据标准进行定义并连接字符串。如果lead为空,则将其视为1,否则为0。
然后,我分别返回3行
MTD
、Current Week
和FTD
,并对从lead得到的sum()
和整个行的count(*)
进行计算。对于MTD,我有本月的总和和计数。
对于Week-它是当前周,而FTD是昨天。
table_mapper
的定义丢失了。此外,可能应该定义一个外键。您的描述并没有详细说明查询的目的。排序顺序是如何定义的?为什么要关心前一行? - Erwin Brandstetter