在 MemSQL 上使用列存储的稀疏矩阵

Sparse matrix using column store on MemSQL

我是列存储数据库系列的新手,有些概念对我来说还不是很清楚。我想用MemSQL来存储稀疏矩阵。

table 看起来像这样:

CREATE TABLE matrix (
r_id INT,
c_id INT,
cell_data VARCHAR(10),
KEY (`r_id`, `c_id`) USING CLUSTERED COLUMNSTORE,
);

查询:

  1. SELECT c_id, cell_data FROM matrix WHERE r_id=<val>; 即整行
  2. SELECT r_id, cell_data FROM matrix WHERE c_id=<val>; 即整列
  3. SELECT cell_data FROM matrix WHERE r_id=<val1> AND c_id=<val2>; 即一个单元格
  4. UPDATE matrix SET cell_data=<val> WHERE r_id=<val1> AND c_id=<val2>;
  5. INSERT INTO matrix VALUES (<v1>, <v2>, <v3>);

查询 1 和 2 的频率差不多,3、4 和 5 的频率也差不多。 Q1,2 中的一个与 Q3,4,5 中的一个频率相同(即 Q1,2:Q3,4,5 ~= 1:1)。

我确实意识到,一次向列存储中插入一行会为每次插入创建行段组,从而降低性能。我无法批量插入。我也不能使用内存中的行存储(矩阵太大)。

我有三个问题:

  1. 如果仅更改 cell_data(即第 4 季度),单行插入的问题是否也涉及更新?

  2. 是否可以在内存行 table 中执行插入(?和更新?)操作并定期将内容批处理到列 table ?

    • 如果我需要最新数据 (?UNION ALL?),我将如何执行 Q1、2?
    • 是否可以避免对两个 tables 执行 Q3(?这意味着两次往返?)?
  3. 我比较关心Q1和Q2的执行速度。聚簇键是否最适合那些。我不确定上面的table如何存储记录。

1。 是的,单行更新也表现不佳 - 它们本质上是删除和插入。

2。 是的,事实上我们在幕后自动执行此操作——最近插入的数据(如果行数太少而不能成为一个好的列段)保存在内存中的行存储形式中,读取查询本质上是查看 UNION ALL 该数据和面向列的数据。然后我们将这些数据批处理以写入面向列的形式。

如果这不够好,根据您的工作量,您可能会受益于明确地将一些数据保存在行存储中 table 而不是依赖上述行为,在这种情况下:

2a。是的,要查看最新数据,您将使用 UNION ALL

2b。数据可能在 table 中,因此您必须查询两者(例如对于 Q1、2,使用 UNION ALL 有效)。这不会进行两次往返,只有一次。

3。 您可以先在列存储键中按 r 或 c 排序 - 在当前模式中为 r。这使得对行的查询变得高效,但是对列的查询将非常低效,它们可能必须基本上扫描完整的 table (取决于数据中的模式)。不幸的是 columnstore tables 不支持使用多个键,所以没有好的方法来解决这个问题。一种潜在的 hacky 解决方案是维护 table 的两份副本,一份使用密钥 (r, c),一份使用密钥 (c, r) - 这实际上是手动维护两个索引。

根据您描述的工作负载,听起来您正在执行许多单行查询(Q3、4、5,占工作负载的 50%),行存储比列存储更适合(参见 http://docs.memsql.com/latest/concepts/columnstore/)。不幸的是,如果它不适合内存,除了添加更多内存之外没有真正解决这个问题的好方法。