查询溢出到磁盘
Posted
技术标签:
【中文标题】查询溢出到磁盘【英文标题】:Query spilling to disk 【发布时间】:2021-06-15 17:48:58 【问题描述】:我们有一个溢出到磁盘的查询(大约 1 TB!),代码如下:
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
);
没有索引,没有约束
谢谢,
【问题讨论】:
您能告诉我们 EXPLAIN (ANALYZE, BUFFERS) 的结果吗?你能告诉我们你的表和索引定义吗?没有这些信息,几乎不可能为您提供帮助。 没问题,我正在运行它,我会尽快将它发布在这里 您使用的是哪个 Postgres 版本? 我们使用的是 9.4.24,它是一个 Greenplum DB 然后尝试删除 CTE。 (这并不是真正需要的开始)。 【参考方案1】:答案已经在你的问题中了
没有索引,没有约束
为了在如此大的表中缩短查询时间,索引的使用势在必行。尝试将部分索引添加到您的表中,以便查询计划者事先知道在哪里可以找到年份和季度,例如
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;
【讨论】:
以上是关于查询溢出到磁盘的主要内容,如果未能解决你的问题,请参考以下文章
鉴于我将 DataBag 溢出到磁盘,为啥此 Pig UDF 会导致“错误:Java 堆空间”?
Pandas to PySpark给出OOM错误而不是溢出到磁盘[重复]
找不到开发人员磁盘映像堆栈溢出 xcode 7.2,iOS 9.3.1 [重复]