提高 PostgreSQL 数组查询的性能

Nix*_*xuz 5 sql arrays postgresql bigdata postgresql-performance

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

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;
Run Code Online (Sandbox Code Playgroud)

该表中的每个条目仅写入一次,并且可能以随机索引多次读取。PostgreSQL 似乎对于查找的扩展性不太好,因为即使将 STORAGE 设置为 EXTERNAL (O(n)) ,向量长度也会增长。这使得像下面这样的查询(我们在数组中选择了许多单独的值)非常非常慢(分钟 - 小时)。

SELECT probeset[2], probeset[15], probeset[102], probeset[1007], probeset[10033], probeset[200101], probeset[1004000] FROM expression LIMIT 1000;
Run Code Online (Sandbox Code Playgroud)

如果拉动足够多的单独索引,它甚至可能比拉动整个数组更慢。

有什么办法可以让这样的查询更快吗?

编辑

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

    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';
    
    Run Code Online (Sandbox Code Playgroud)

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

  • 目前最长的单个数组为 140 万个,其他较短,最小的为 22,000 个,平均长度约为 10 万个项目。

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

Pat*_*ick 4

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

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

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

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

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