Sql 红移更新使用Seq扫描非常慢

Sql 红移更新使用Seq扫描非常慢,sql,amazon-redshift,Sql,Amazon Redshift,我必须在一个大表(6亿行)中更新大约300行,我正在努力加快更新速度 我使用的查询有点棘手: UPDATE my_table SET name = CASE WHEN (event_name in ('event_1', 'event_2', 'event_3')) THEN 'deleted' ELSE name END WHERE uid IN ('id_1', 'id_2') 我尝试在这个查询中使用EXPLAIN,我得到: XN Seq Scan on my_table (cost=

我必须在一个大表(6亿行)中更新大约300行,我正在努力加快更新速度

我使用的查询有点棘手:

UPDATE my_table
SET name = CASE WHEN (event_name in ('event_1', 'event_2', 'event_3')) 
THEN 'deleted' ELSE name END
WHERE uid IN ('id_1', 'id_2')
我尝试在这个查询中使用EXPLAIN,我得到:

XN Seq Scan on my_table  (cost=0.00..103935.76 rows=4326 width=9838)
   Filter: (((uid)::text = 'id_1'::text) OR ((uid)::text = 'id_2'::text))
我有一个交错的sortkey,uid是这个sortkey中包含的列之一。 查询看起来像这样的原因是,在实际上下文中,集合中的列数(以及名称)可能会有所不同,但可能不会超过10。 基本思想是我不希望交叉连接(更新规则是特定于列的,我不希望将它们混合在一起)。 例如,将来会出现如下查询:

UPDATE my_table
SET name = CASE WHEN (event_name in ("event_1", "event_2", "event_3")) THEN 'deleted' ELSE name END,
address = CASE WHEN (event_name in ("event_1", "event_4")) THEN 'deleted' ELSE address END
WHERE uid IN ("id_1", "id_2")
无论如何,回到第一个查询,它会运行很长时间(大约45分钟),并且需要100%的CPU

我尝试检查更简单的查询:

explain UPDATE my_table SET name = 'deleted' WHERE uid IN ('id_1', 'id_2')
XN Seq Scan on my_table  (cost=0.00..103816.80 rows=4326 width=9821)
   Filter: (((uid)::text = 'id_1'::text) OR ((uid)::text = 'id_2'::text))

我不知道还有什么可以补充的,我很乐意听到任何建议。

您是否尝试过删除交错排序键,并将其替换为
uid
上的简单排序键或第一列为
uid
的复合排序键

此外,名称
uid
使我认为您可能正在使用GUID/UUID作为值。对于红移中的
id
值,尤其是排序键,我建议这是一个反模式

GUID/UUID
id
存在问题:

  • 不要以可预测的顺序发生
    • 通常会触发完整的顺序扫描
    • 新行总是破坏排序
  • 压缩得很差
    • 需要更多的磁盘空间进行存储
    • 查询时需要读取更多数据

    • 红移中的更新是删除,然后插入。按设计红移只是将行标记为已删除,而不是实际删除它们(重影行)。显式仅真空删除回收空间所需的


      如下。受这些重影行影响的扫描。建议稍后运行上述命令并检查查询性能。

      实际查询必须完全不同,因为CASE语句中的WHERE关键字会导致错误。里面有子选择吗?还有,表上的distkey是什么?啊,的确,现在更正了。我觉得你的问题没问题。我自己在交错排序键方面运气不太好。在不属于排序键的列上进行过滤,使用复合排序键与交错排序键相比,我仍然获得了大约10倍的改进。在sortkey列上进行过滤应该更好。我们放弃使用交错键,直到Redshift将它们分类。我的另一个建议是,您尝试找到其他方法来限制搜索。例如,如果有时间戳。如果您知道您要查找的事件必须在最近几天内发生,则可以极大地限制要查看的表的数量。任何作为排序键之一的字段都应该有帮助。不幸的是,这个想法基本上是编辑给定uid的所有事件。因此,没有太多的方法来进一步限制它。但是谢谢你的建议!是的,uid是MongoId字符串。刚意识到sortkey至少最有可能不起作用,因为在6亿行中只有几百万行被排序。这可能需要回答另一个问题,但也许您可以提出一些建议:如果一个表太大,清理时间太长,而深度复制需要的磁盘空间比可用空间更多,那么还有什么其他方法可以重新索引该表?这取决于表的大小。对于一个真正庞大的表,您可以考虑将其拆分为包含有限数据集(例如一周或一个月)的较小表,并在这些表上使用
      UNION ALL
      视图替换原始表。您没有提到您的
      DISTSTYLE
      -我会尝试使用
      uid
      作为分发键,并在时间戳列上使用排序键。如果没有空间,您可以对S3进行增量卸载,删除卸载的范围,然后从S3复制回新表。另外,如果您有空间问题并且还没有启用压缩,这将是一个很好的机会:。@JoeHarris我正在使用带有时间戳sortkey的GUID distkey,并且对distkey的查询筛选速度非常慢。不使用该筛选器的查询速度非常快。查找单个GUID值并使其成为dist键非常昂贵,在这方面并没有真正的帮助。尝试将其添加到排序键。这将使吸尘更昂贵(因为上面提到的问题),但应该会提高查询性能。