【发布时间】:2017-12-20 22:57:42
【问题描述】:
TLDR:我需要对 web 应用程序的大型数据集进行多个中值聚合,但性能很差。对于这个用例,我的查询是否可以改进/是否有比 AWS Redshift 更好的数据库?
我正在开展一个团队项目,该项目涉及通过我们的网络应用程序按需聚合大型数据集以进行可视化。我们使用的 Amazon Redshift 加载了近 1,000,000,000 行、按日期排列的 dist-key(我们拥有从 2014 年至今的数据,每天摄取 900,000 个数据点)和按唯一 ID 排列的排序键。唯一 id 可能与其他唯一 id 具有一对多的关系,对于这种关系,“多”关系可以被认为是 id 的“孩子”。
出于保密考虑,请考虑这样的表结构
TABLE NAME: meal_nutrition
DISTKEY(date),
SORTKEY(patient_id),
patient_name varchar,
calories integer,
fat integer,
carbohydrates integer,
protein integer,
cholesterol integer,
sodium integer,
calories integer
TABLE NAME: patient_hierarchy
DISTKEY(date date),
SORTKEY(patient_id integer),
parent_id integer,
child_id integer,
distance integer
把这个想象成一个有医生等级的世界。患者被封装为实际患者和医生本身,医生可以是其他医生的患者。医生可以随时转让患者/医生的所有权,所以层次结构不断变化。
DOCTOR (id: 1)
/ \
PATIENT(id: 2) DOCTOR (id: 3)
/ \ \
P (id: 4) D (id: 8) D(id: 20)
/ \ / \ / \ \
................
我们遇到问题的一个可视化(由于性能)是时间序列图,它显示了默认日期范围必须为 1 年的多个指标的每日中位数。所以在这个例子中,我们想要一个病人/医生和他们的“孩子”消耗的所有膳食的脂肪、碳水化合物和蛋白质的中位数,给定一个病人 ID。使用的查询是:
SELECT patient_name,
date,
max(median_fats),
max(median_carbs),
max(median_proteins)
FROM (SELECT mn.date date,
ph.patient_name patient_name,
MEDIAN(fats) over (PARTITION BY date) AS median_fats,
MEDIAN(carbohydrates) over (PARTITION BY date) AS median_carbs,
MEDIAN(proteins) over (PARTITION BY date) AS median_proteins
FROM meal_nutrition mn
JOIN patient_hierarchy ph
ON (mn.patient_id = ph.child_id)
WHERE ph.date = (SELECT max(date) FROM patient_hierarchy)
AND ph.parent_id = ?
AND date >= '2016-12-17' and date <= '2017-12-17'
)
GROUP BY date, patient_name
此查询中最繁重的操作是对每个中位数的排序(每个都需要对 ~200,000,000 行进行排序),但我们无法避免这种情况。因此,此查询需要大约 30 秒才能完成,这意味着用户体验不佳。我正在做的查询可以改进吗?这种用例有更好的数据库吗?谢谢!
【问题讨论】:
-
不要在日期上分布,在连接列上分布。使用日期作为排序键。 aws.amazon.com/blogs/big-data/…
标签: postgresql bigdata amazon-redshift rdbms datastore