为什么在将已排序的行插入到已排序的数据库表中时,如果这些行最后没有附加,那么真的需要诉诸



假设我们有一个排序的表a和一个排序表B,我们想在a中插入B的所有行。

根据我目前所读的内容(如果我错了,请纠正我),从B插入A中的行将导致一个未排序的表,除非B的排序键值都大于A的最大排序键值(例如,B是时间序列A的延续,排序键是时间戳)。

根据我的理解,在任何情况下都应该可以合并A中B的行,同时通过在A中插入B的每个元素来保持结果数组的排序,一次插入一个。这将导致比附加所有内容和运行通用排序算法更低的计算复杂度

然而,我找不到任何选项可以在Redshift或MySQL等数据库上执行这样的操作。这样的事情可能发生吗?如果不是,为什么?是否存在使这种想法效率低下的限制?

由于这个问题被标记为Amazon Redshift,我假设这个问题是专门关于Redshift的。

Redshift是一个列数据库,其中所有列数据存储在一起;块";大小为1MB。这样做的目的是为了读取单列不需要从可能长达数十亿项的列表中进行索引。因此,每列的数据都被分解成1MB的块,这些块有元数据来存储每个块包含的信息。两条元数据信息是块中的最大值和最小值。

如果您想在ID列中找到特定的ID值,Redshift可以首先检查所有ID列块的元数据,并只读取那些可能包含您要查找的ID的块。现在,如果表中的数据存储是以某种随机顺序存储的(wrt ID),那么对于所有块元数据,您要查找的ID很可能在max和min之间,并且需要读取大量数据才能找到您的ID。但是,如果您的表是按ID排序的,则元数据搜索将只导致需要读取一个块。有问题的块的行号可用于查找其他列的块,因此这些列也只需要读取有限数量的块。

关于这些块的另一个重要因素是它们是不可变的——一旦写入,它们就不会改变。如果一个块需要更新,它将被完全替换。这是为了确保在任何时间点,对于任何查看器,表都是一致的,并且可以支持多个版本的表,这样查看不同版本表的用户就可以看到其版本的一致数据。(这种一致性系统被称为MVCC-多版本一致性控制。)在Redshift中,信息的最小一致块是1MB块。

因此,在表A和表B的场景中,您是正确的,将这些表组合在一起是可能的。甚至还有一个命令可以做到这一点——ALTER TABLE APPEND,它从一个表中获取块,并将它们与另一个表相关联。如果你愿意的话,可以做块移植。显然,这些表需要具有相同的DDL才能工作。这些块的元数据也将从源表移动到另一个表。运行此命令后,源表将为空,因为它的块已链接到另一个表。

相反,您可以将数据从一个表插入到另一个表中。在这种情况下,来源表将包含操作后的所有数据。";新的";添加的行将在接收表中创建新的块,数据的顺序将取决于写入数据的顺序(例如,insert语句中的order by子句)。这些新块一旦有了元数据,就会有表示每个块所拥有数据的最大和最小范围的元数据。

假设在这两种情况下,添加的新数据也按照我们的示例中的ID进行排序。新块和旧块可能具有重叠的范围,因此我们对特定ID的搜索可能返回两个块。两个街区仍然比所有街区要好得多。情况还是不错的。

如果我们想把数据按完美的排序顺序放在磁盘上,我们需要对表进行真空处理。这是Redshift上打开(潜在地)表的所有块以重新排序数据的过程;合并";如您所述的行数据。这将使我们回到ID示例中的一个匹配块。

更直接地回答你的问题-在Redshift中,块是不可变的,所有添加到表中的新数据都被附加到";结束";在新的区块中。致";合并";按照旧数据的排序顺序排列的新数据需要对表进行真空处理。真空过程(潜在地)为表写入所有新块,并且一旦完成,MVCC系统就改变表的哪个版本对所有用户可见。

数据存储管理对于每个数据库设计都是非常具体的。这些信息是针对Redshift的,MySQL是一个不同的野兽,有着不同的体系结构。

最新更新