假设我们有一个排序表A和一个排序表B,我们希望将B的所有行插入到A中。
根据我到目前为止所读到的内容(如果我错了,请更正),将A中的行从B中插入将导致一个未排序的表,除非B的排序键值都大于A的最大排序键值(例如B是时间序列A的延续,而排序键是时间戳)。
根据我的理解,在任何情况下都应该可以合并A中的B行,同时通过在A中插入每个B的元素来保持结果数组的排序,一次一个。这将导致比附加所有内容和运行通用排序算法更低的计算复杂度。
但是,我找不到在诸如Redshift或MySQL这样的数据库上执行这样的操作的任何选项。这样的事有可能吗?如果不是,那是为什么?是否存在限制因素使这种想法效率低下?
发布于 2021-12-22 17:19:29
由于这个问题被标记为Amazon,我将假设这个问题是专门关于Redshift的。
Redshift是一个柱状数据库,所有列数据都存储在一起,但它被分解为大小为1MB的“块”。这样做是为了使读取单个列不需要从可能有数十亿项的列表中索引。因此,每一列的数据被分解为1MB块,并且这些块具有针对它们的元数据来存储关于每个块包含什么的信息。两个元数据信息是块中的最大值和最小值。
如果您想在ID列中找到一个特定的ID值,Redshift可以首先检查所有ID列块的元数据,并且只读取那些可能包含您要查找的ID的块。现在,如果表中的数据存储以某种随机顺序(wrt )存储,那么对于所有块元数据来说,您要查找的ID很可能介于最大值到最小之间,需要读取大量数据才能找到您的ID。但是,如果您的表是按ID排序的,则元数据搜索只需要读取一个块。有关块的行号可用于查找其他列的块,因此也只需要为这些列读取有限数量的块。
关于这些块的另一个重要因素是它们是不可变的--一旦写入它们就不会改变。如果需要更新块,则完全替换。这是为了确保在任何时候,任何查看器表都是一致的,并且可以支持表的多个版本,以便查看不同版本的表的用户可以看到其版本的一致数据。(这个一致性系统称为MVCC -多版本一致性控制。)Redshift中的最小相干信息块是1MB块。
因此,在表A和表B的场景中,合并这些表是可能的,这是正确的。甚至还有一个命令来执行这个- ALTER追加,它从一个表中获取块并将它们与另一个表关联。如果你愿意的话。显然,这些表需要具有相同的DDL才能工作。这些块的元数据也将从源表移动到另一个。在运行此命令后,资源表将为空,因为它的块已链接到另一个表。
相反,您可以将数据从一个表插入到另一个表中。在这种情况下,采购表将包含操作后的所有数据。添加的“新”行将在接收表中创建新的块,数据的顺序将取决于写入的数据的顺序(例如,insert语句中的order子句)。这些新块一旦有了元数据,就会有表示每个块拥有的数据的最大和最小范围的元数据。
让我们假设,在这两种情况中,添加的新数据也是按ID对每个示例进行排序的。新块和旧块可能有重叠的区段,因此搜索特定的ID可以返回两个块。两个街区仍然比所有的街区好得多。仍然是个好情况。
如果我们想在磁盘上将数据放入完美的排序顺序,我们将需要对表进行真空处理。这是Redshift上的过程,用于打开(可能)表的所有块,重新排序数据,并如您所说的“合并”行数据。这将使我们回到ID示例中的一个匹配块。
为了更直接地回答您的问题,Redshift中的块是不可变的,所有添加到表中的新数据都会附加到新块中的"end“。若要按排序顺序将新数据与旧数据“合并”,表需要为VACUUMed。真空处理(可能)为表写入所有新块,一旦完成MVCC系统更改,表的哪个版本对所有用户都是可见的。
数据存储管理对于每个数据库的设计都是非常具体的。这个信息是给Redshift的,MySQL是一个不同的野兽,有着不同的架构。
https://stackoverflow.com/questions/70450439
复制相似问题