【发布时间】:2017-06-26 08:27:27
【问题描述】:
我在我自己的机器上为这个数据库使用 PostgreSQL 9.6.1。
我有这个交易数据库。整个数据库大约有 1 亿行 x 30 列。交易跨越过去四年。
对于这个查询,有三个相关的列:
- 交易时间戳,四舍五入到最近的 15 分钟
- 供应商 ID
- 交易金额(收入)
我有兴趣返回四列的输出,例如下图(抱歉链接 - 还没有足够的代表来嵌入图像:
输出是该特定时间戳期间的交易计数、过去 60 分钟内唯一活跃供应商的计数以及过去 60 分钟内的每小时收入。
以下是我用来尝试完成此操作的代码。
SELECT transaction_timestamp,
COUNT(transaction_timestamp) AS "transaction_timestamp",
(SELECT COUNT(DISTINCT vendor_id)
FROM transactions_db
WHERE transaction_timestamp BETWEEN t.transaction_timestamp - INTERVAL '60 MINUTES' AND t.transaction_timestamp
) AS "lag_60_transaction_count",
(SELECT SUM(revenue) / COUNT(DISTINCT vendor_id)
FROM transactions_db
WHERE transaction_timestamp BETWEEN t.transaction_timestamp - INTERVAL '60 MINUTES' AND t.transaction_timestamp
) AS "rolling_hourly_rate"
FROM transactions_db t
GROUP BY transaction_timestamp
ORDER BY transaction_timestamp;
这里是解释输出:
GroupAggregate (cost=21989857.85..681893649752.90 rows=108423 width=56)
Group Key: t.transaction_timestamp
-> Sort (cost=21989857.85..22252785.49 rows=105171056 width=8)
Sort Key: t.transaction_timestamp
-> Index Only Scan using timestamp_vendor_revenue_idx on transactions_db t (cost=0.57..3663118.41 rows=105171056 width=8)
SubPlan 1
-> Aggregate (cost=3143836.32..3143836.33 rows=1 width=8)
-> Index Only Scan using timestamp_vendor_revenue_idx on transactions_db (cost=0.57..3142521.68 rows=525855 width=4)
Index Cond: ((transaction_timestamp >= (t.transaction_timestamp - '01:00:00'::interval)) AND (transaction_timestamp <= t.transaction_timestamp))
SubPlan 2
-> Aggregate (cost=3145150.96..3145150.97 rows=1 width=32)
-> Index Only Scan using timestamp_vendor_revenue_idx on transactions_db transactions_db_1 (cost=0.57..3142521.68 rows=525855 width=10)
Index Cond: ((transaction_timestamp >= (t.transaction_timestamp - '01:00:00'::interval)) AND (transaction_timestamp <= t.transaction_timestamp))
话虽如此,这个查询运行时间非常长(8 多个小时 - 运行了一夜,今天早上仍在运行)。
我在 transaction_timestamp、vendor_id 和收入上创建了一个复合索引,但运行时间仍然非常高。
当我对数据子集(我有一个包含一天数据的示例表)运行此查询时,查询会在 2.1 秒内返回。
我对优化数据库和查询非常熟悉,所以我可以在 2.1 秒内返回一天的数据,这一事实让我相信我可以做一些事情来让这个查询在主数据库的合理时间。
如果我遗漏了任何其他信息,请告诉我。
这里的示例数据、查询和输出:http://rextester.com/AOKNT5900
【问题讨论】:
-
能否提供您的
CREATE TABLE以查看索引? -
@JuanCarlosOropeza 您是否想过将所有数据发送到 GPU,以便在计算密集型的情况下它可以更快地完成任务?
-
@huseyintugrulbuyukisik 不,我说 1 亿个表查询不需要 8 小时。
-
@JuanCarlosOropeza 100mm 是数百万。索引是在创建表之后创建的 - 就是这样:
CREATE INDEX timestamp_vendor_revenue_idx ON transactions_db (vendor_id, transaction_timestamp, revenue) -
即使索引是在表之后创建的,也可以从pgAdmin获取
create table脚本。
标签: sql database postgresql