【问题标题】:Improve performance of PostgreSQL array queries提高 PostgreSQL 数组查询的性能
【发布时间】:2015-07-11 22:34:05
【问题描述】:

我在 PostgreSQL 表中存储双精度的大型向量(140 万个值)。该表的创建语句如下。

CREATE TABLE analysis.expression
(
  celfile_name character varying NOT NULL,
  core double precision[],
  extended double precision[],
  "full" double precision[],
  probeset double precision[],
  CONSTRAINT expression_pkey PRIMARY KEY (celfile_name)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE analysis.expression ALTER COLUMN core SET STORAGE EXTERNAL;
ALTER TABLE analysis.expression ALTER COLUMN extended SET STORAGE EXTERNAL;
ALTER TABLE analysis.expression ALTER COLUMN "full" SET STORAGE EXTERNAL;
ALTER TABLE analysis.expression ALTER COLUMN probeset SET STORAGE EXTERNAL;

此表中的每个条目仅写入一次,并且可能在随机索引处读取多次。 PostgreSQL doesn't seem to scale terribly well for lookups as the vector length grows even with STORAGE set to EXTERNAL (O(n))。这使得查询如下,我们在数组中选择了许多单独的值,非常非常慢(分钟 - 小时)。

SELECT probeset[2], probeset[15], probeset[102], probeset[1007], probeset[10033], probeset[200101], probeset[1004000] FROM expression LIMIT 1000;

如果有足够多的单个索引被拉取,它甚至可能比拉取整个数组还要慢。

有什么方法可以使此类查询更快?

编辑

  • 我使用的是 PostgreSQL 9.3。
  • 我正在运行的所有查询可能都是简单的选择

    SELECT probeset[2], probeset[15], probeset[102], probeset[1007], probeset[10033], probeset[200101], probeset[1004000] FROM expression JOIN samples s USING (celfile_name) WHERE s.study = 'x';
    

    在一种情况下,这些查询的结果是通过预测模型提供的。预测概率被存储回另一个表的数据库中。在其他情况下,从数组中提取选择项目以进行下游分析。

  • 目前最长的单个数组是 140 万个,其他较短,最小的为 22000 个,平均长度约为 100000 个。

  • 理想情况下,我会将数组数据存储为一个宽表,但是如果我们想要提取一个 140 万个条目,那么长表(即具有 celfile_name、索引、值的行)比 PostgreSQL 数组慢得多来自数据库的数据的完整数组。我们这样做是为了在对完整数据集进行分析时加载下游数据存储。

【问题讨论】:

  • 我怀疑 Postgres 在对其进行任何操作之前需要读取整个数组。最好将值存储为表中的行,即使表表示更大。
  • 您实际上在 PostgreSQL 中存储大型数组,您只是存储对外部存储的引用。除非您在查询中使用数组中的数据将其与其他关系中的数据相结合,否则 PostgreSQL 的使用效率将不高。您如何使用 PostgreSQL 中的数据?您能否详细说明数组中的数据代表什么(例如时间序列?)以及四个数组之间的关系(f.i.每个数组中相同索引处的数据是否相关?)?所有四个数组的值都是 1.4M 长还是聚合大小?
  • 对于性能问题来说,提供正在使用的 Postgres 版本应该是显而易见的。无需事先询问。
  • @GordonLinoff - 我编辑了这个问题来解释为什么将值存储在 PostgreSQL 表中是不可行的。
  • @Patrick - 我更新了这个问题,更深入地了解了将要运行的其他查询。简而言之,每个数组的长度可以非常长,最长的单个数组是 140 万个项目。跨数组的相同索引不相关。

标签: sql arrays postgresql bigdata postgresql-performance


【解决方案1】:

您将数据存储在结构化数据管理存储容器(即 PostgreSQL)中,但由于数据的性质(即类似数据的大型但不规则大小的集合),您实际上将数据存储在外部 的容器。 PostgreSQL 不擅长从不规则和不可预测的数据中检索数据?)如您所见;数组存储在外部的事实已经证明了您的要求与 PostgreSQL 擅长的地方不一致。很可能有比 PostgreSQL更好 存储和读取数组的解决方案。鉴于通过预测模型分析数组的结果存储在 PostgreSQL 数据库的某些表中,这暗示了一种混合解决方案:以某种形式存储您的数据,以允许以您需要的模式进行有效访问,然后将结果存储在 PostgreSQL 中进一步处理。

由于您没有提供有关预测模型的任何详细信息,因此无法在此答案中具体说明,但我希望这对您有所帮助。

如果您的预测模型是用 PostgreSQL 驱动程序可用的某种语言编写的,则以适合该语言的某种格式存储您的数据,进行预测并将结果写入 PostgreSQL 中的表。这适用于使用 pq 库的 C 和 C++ 等语言,以及使用 JDBC 等高级库的 Java、C#、Python 等。

如果您的预测模型是用 MatLab 编写的,则以 MatLab 格式存储您的数组并连接到 PostgreSQL 以获取结果。如果用 R 编写,您可以使用 PostgreSQL 的 R 扩展。

这里的关键是您应该以一种允许在预测模型中有效使用的形式存储数组。将您的数据存储与预测模型相匹配,而不是相反。

【讨论】:

  • 这或多或少是我们在当前解决方案中所做的。我们正在使用 postgreSQL 来存储我们的元信息,并且我们有两个用于这些大型表达式数据数组的下游数据存储。一个存储是自定义的 2D 键值,在内存中,数据存储,对于 1 - 1000 个数组索引的查询来说是快速的。另一个存储是大型二进制文件,它本质上是内存映射为大型 C 风格的 2D 矩阵,如果我们需要加载大量索引进行分析,它可以更好地扩展。理想情况下,我们可以使用 PostgreSQL 数组访问来替换自定义的 2D 键值存储。
猜你喜欢
  • 2021-08-03
  • 2013-02-17
  • 1970-01-01
  • 2017-11-23
  • 2018-10-19
  • 2021-07-30
  • 2022-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多