一尘不染

MySQL 能否合理地对数十亿行进行查询?

mysql

我计划将质谱仪的扫描结果存储在 MySQL 数据库中,并想知道存储和分析这些数据量是否可行。我知道性能因环境而异,但我正在寻找粗略的数量级:查询需要 5 天还是 5 毫秒?

输入格式

每个输入文件包含光谱仪的单次运行;每次运行都由一组扫描组成,每个扫描都有一个有序的数据点数组。有一些元数据,但文件的大部分由 32 位或 64 位整数或浮点数组组成。

Host system

|----------------+-------------------------------|
| OS             | Windows 2008 64-bit           |
| MySQL version  | 5.5.24 (x86_64)               |
| CPU            | 2x Xeon E5420 (8 cores total) |
| RAM            | 8GB                           |
| SSD filesystem | 500 GiB                       |
| HDD RAID       | 12 TiB                        |
|----------------+-------------------------------|

服务器上还有一些其他服务在使用可忽略不计的处理器时间运行。

File statistics

|------------------+--------------|
| number of files  | ~16,000      |
| total size       | 1.3 TiB      |
| min size         | 0 bytes      |
| max size         | 12 GiB       |
| mean             | 800 MiB      |
| median           | 500 MiB      |
| total datapoints | ~200 billion |
|------------------+--------------|

数据点总数是一个非常粗略的估计。

拟议架构

我正计划做“正确”的事情(即疯狂地规范化数据),所以会有一个runs表,spectra一个外键为的表runs,以及一个外键为 的datapointsspectra

2000 亿数据点问题

我将跨多个光谱甚至可能多次运行进行分析,从而产生可能涉及数百万行的查询。假设我正确地索引了所有内容(这是另一个问题的主题)并且我没有尝试在网络上随机播放数百个 MiB,那么 MySQL 处理这个问题是否合理?

附加信息

扫描数据将来自基于 XML 的 mzML格式的文件。这种格式的 <binaryDataArrayList>核心在于存储数据的元素。每次扫描都会产生 >= 2 个<binaryDataArray>元素,这些元素合起来形成 2 维(或更多)形式的数组[[123.456, 234.567, ...], ...]

这些数据是一次性写入的,所以更新性能和事务安全不是问题。

我对数据库模式的幼稚计划是:

runs table

| column name | type        |
|-------------+-------------|
| id          | PRIMARY KEY |
| start_time  | TIMESTAMP   |
| name        | VARCHAR     |
|-------------+-------------|

spectra table

| column name    | type        |
|----------------+-------------|
| id             | PRIMARY KEY |
| name           | VARCHAR     |
| index          | INT         |
| spectrum_type  | INT         |
| representation | INT         |
| run_id         | FOREIGN KEY |
|----------------+-------------|

datapoints table

| column name | type        |
|-------------+-------------|
| id          | PRIMARY KEY |
| spectrum_id | FOREIGN KEY |
| mz          | DOUBLE      |
| num_counts  | DOUBLE      |
| index       | INT         |
|-------------+-------------|

这合理吗?


因此,正如您可能已经推断出的那样,我是程序员,而不是实验室的生物学家,所以我对科学的了解几乎不及真正的科学家。

这是我将要处理的那种数据的单一频谱(扫描)图:

查看器屏幕截图

该软件的目标是找出峰值的位置和重要性。我们现在使用专有软件包来解决这个问题,但我们想编写自己的分析程序(用 R 语言),这样我们就知道表底下到底发生了什么。如您所见,绝大多数数据都是无趣的,但我们不想丢弃我们的算法遗漏的潜在有用数据。一旦我们有了一个我们满意的可能峰值列表,管道的其余部分将使用该峰值列表而不是原始数据点列表。我认为将原始数据点存储为一个大 blob 就足够了,因此可以在需要时重新分析它们,但仅将峰值保留为不同的数据库条目。在那种情况下,每个光谱只有几十个峰值,所以疯狂的缩放比例不应该


阅读 132

收藏
2022-11-29

共1个答案

一尘不染

我不太了解您的需求,但也许将每个数据点存储在数据库中有点过分了。这听起来几乎像是通过将每个像素作为单独的记录存储在关系数据库中来存储图像库的方法。

一般来说,在数据库中存储二进制数据在大多数情况下都是错误的。通常有更好的方法来解决问题。虽然将二进制数据存储在关系数据库中并没有本质上的错误,但往往弊大于利。顾名思义,关系数据库最适合存储关系数据。二进制数据不是关系数据。它会增加数据库的大小(通常是显着增加),可能会损害性能,并可能导致有关维护十亿条记录的 MySQL 实例的问题。好消息是有些数据库特别适合存储二进制数据。其中之一,虽然并不总是很明显,但就是您的文件系统!简单地为你的二进制文件想出一个目录和文件命名结构,

另一种方法是将基于文档的存储系统用于您的数据点(可能还有光谱)数据,并使用 MySQL 进行运行(或者可能将运行与其他运行放入相同的数据库中)。

2022-11-29