【问题标题】:What's an Efficient Alternative to LIMIT?LIMIT 的有效替代方案是什么?
【发布时间】:2019-02-11 09:56:40
【问题描述】:

我的问题基本上是:如何告诉我的数据库在第一次匹配我的 WHERE 条件后进行 seq 扫描并停止?

假设我想找到某种类型的第一个事件,我可以编写以下查询:

select *
from installs
where country = 'China' 
order by install_date
limit 1

这里的问题是,引擎会根据操作顺序扫描所有表并生成与我的过滤器匹配的数据集,然后对该数据集进行排序(成本巨大),然后仅返回第一行。

我当然可以按特定日期进行过滤,但假设我不知道要过滤的时间段 - 如何在 Amazon Redshift 中优化这种类型的查询(可能在 where 子句中)?

【问题讨论】:

  • 如果您没有办法在install_date 上创建索引(或安排其他一些字段,例如记录ID 遵循相同的顺序),您无能为力。数据库必须检索和排序所有匹配的记录。
  • 您可以使用 install_date 作为表格的排序键。
  • 除非查看所有install_date,否则数据库应该如何知道哪个是最小的?
  • 您可以使用排序键做您想做的事情:docs.aws.amazon.com/redshift/latest/dg/…
  • 这是您尝试执行的实际查询的示例吗?如果是,那么 Redshift 可能不适合您。如果您的行数少于 100,000,000 行,那么您可能会发现标准 Postgres 数据库足以满足您的需求。

标签: sql amazon-web-services amazon-redshift sqlperformance


【解决方案1】:

Redshift 的一般策略是进行大量扫描,但将其并行化。任何涉及获得单行的情况都不是理想的。也就是说,您可以做四件事:

1.将扫描减少到一个点

如果国家/地区始终是过滤的字段,请先将表的排序键设置为国家/地区的复合排序键。

2。无需排序

执行ORDER BY x LIMIT 1 的更有效方法通常是 MAX。

那就试试吧

SELECT *
FROM installs
WHERE pk = (
  SELECT MAX(pk)  -- or install_date, if install date is unique
  FROM installs
  WHERE country = 'China'
)

3.在面向行和列之间调整选定的列

要求像 Redshift 这样的列式数据库选择 * 会导致每列的成本。尝试只选择您需要的列。

4.添加更多节点,因此每个节点执行的扫描更少

(确保数据没有全部设置为分布样式)

【讨论】:

  • 非常感谢您的详细回答。我实际上没有在查询中选择 *,我将在帖子中对其进行编辑。关于最大聚合函数 - 它不需要排序作为前提条件?
  • 没有。如果我给您一个列表,例如 [8,2,13,4,9,1,7],您是否必须对整个事物进行排序才能找到最大值?不,您只需通过一次,记住单个最高值并忘记其余的值
【解决方案2】:

如果你删除ORDER BY,那么它可以有效地工作。

对结果进行排序的要求意味着它需要检查国家为中国的所有行,这对于返回一项效率不高。

where country = 'China' 子句在 SORTKEY = country 时是有效的,因为它可以跳过任何不包含所需值的存储块。如果匹配的行相对较少,这将非常有效。

如果您经常查询单行结果,则可能值得将此类信息存储在单独的表中以加快查找速度。该值可以根据需要每天或每小时计算一次。

【讨论】:

  • 但是如果你去掉order by,结果不能保证返回第一个事件,它可能是任何匹配where子句的事件。
  • 是的。但它是有效的! :)
猜你喜欢
  • 2017-11-17
  • 2022-08-13
  • 2021-11-13
  • 2018-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-08
相关资源
最近更新 更多