1

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

该表看起来像这样:

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如果仅更改(即 Q4),单行插入的问题是否也涉及更新?

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

    • 如果我需要最新数据(?UNION ALL?),我将如何执行 Q1,2?
    • 是否可以避免为两个表执行 Q3(?这意味着两次往返?)?
  3. 我担心 Q1 和 Q2 的执行速度。Clustered 键对于那些是最优的。我不确定如何使用上面的表格存储记录。

4

1 回答 1

1

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

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

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

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

2b。数据可能在任一表中,因此您必须同时查询两者(例如 Q1,2,使用 UNION ALL 有效)。这不会做两次往返,只有一次。

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

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

于 2015-12-08T20:24:14.017 回答