问题描述
WITH q (year,quarter) AS ( SELECT * FROM temp.quarters) SELECT *,(SELECT price FROM prices WHERE EXTRACT(QUARTER FROM
pricing_date::TIMESTAMP) = q.quarter AND EXTRACT(YEAR FROM
pricing_date::TIMESTAMP) = q.year ORDER BY pricing_date LIMIT 1) FROM
q ORDER BY q.year,q.quarter
价格表有数百万行,有没有办法改进这个查询,使其不会溢出太多?我们认为这可能是因为我们使用的是“With”子句而不是临时表?
表定义如下:
CREATE TABLE public.record_pricing (
record_id int8 NOT NULL,pricing_date date NOT NULL,price numeric(26,10) NOT NULL,)
WITH (
appendonly=true
);
没有索引,没有约束
谢谢,
解决方法
答案已经在你的问题中
没有索引,没有约束
为了在如此大的表中提高查询时间,索引的使用势在必行。尝试将部分索引添加到您的表中,以便查询平面预先知道在哪里可以找到年份和季度,例如
CREATE INDEX idx_pricing_quarter ON record_pricing (EXTRACT(QUARTER FROM pricing_date::TIMESTAMP));
CREATE INDEX idx_pricing_year ON record_pricing (EXTRACT(YEAR FROM pricing_date::TIMESTAMP));
.. 甚至
CREATE INDEX idx_pricing_year_quarter ON record_pricing
(EXTRACT(QUARTER FROM pricing_date::TIMESTAMP),EXTRACT(YEAR FROM pricing_date::TIMESTAMP));
您可能还想考虑将 pricing_date
编入索引,请查看 documentation
CREATE INDEX idx_pricing_date ON record_pricing (pricing_date);
请注意,索引可能会减慢表中的 INSERTS
速度!但由于它很可能是一个数据仓库,所以这可能不是问题。
之后,您的查询应该会变得更快。查看您的查询是否正确使用索引的最佳方法是 EXPLAIN
它。玩玩它,你会自己看到改进。
顺便说一句,CTE 不是这里的问题,因为它是在一个可能很小的表 temp.quartes
中的完整扫描,但是如果您想摆脱它,请尝试:
SELECT q.year,q.quarter,(SELECT price
FROM record_pricing
WHERE EXTRACT(QUARTER FROM pricing_date::TIMESTAMP) = q.quarter AND
EXTRACT(YEAR FROM pricing_date::TIMESTAMP) = q.year
ORDER BY pricing_date LIMIT 1)
FROM quarters q;