如何给这个表做最佳索引?

问题描述 投票:0回答:1

我在PostgreSQL中有一个大表(>2000 M行),必须尽快查询。它代表了生物样本中基因表达的测量结果。事情是,有时测量是直接在基因上进行的("探针 "则为NULL),有时测量是通过一个基因的 "探针 "来完成的("基因 "则仍为设置)。一个基因可以有多个探针。没有其他表包含基因-探针的关系。

CREATE TABLE "gene_measurements" (
  "gene" INTEGER NOT NULL REFERENCES "genes" ON DELETE CASCADE,
  "sample" INTEGER NOT NULL REFERENCES "samples" ON DELETE CASCADE,
  "probe" INTEGER REFERENCES "probes" ON DELETE CASCADE,
  "value" REAL NOT NULL
);

常见的查询包括获取给定样本中所有基因的表达,获取给定基因探针在所有样本中的表达,或者获取给定基因探针在给定样本中的表达。

现在的情况是,我有以下覆盖索引。它工作得很好,但非常耗费空间。

CREATE INDEX "gene_measurements_gene_sample_value_index" ON "gene_measurements" ("gene", "sample", "value");
CREATE INDEX "gene_measurements_sample_gene_value_index" ON "gene_measurements" ("sample", "gene", "value");
CREATE INDEX "gene_measurements_sample_probe_value_index" ON "gene_measurements" ("sample", "probe", "value");
CREATE INDEX "gene_measurements_probe_sample_value_index" ON "gene_measurements" ("probe", "sample", "value");

有没有什么聪明的办法可以让我在保持速度的同时,得到一个更整洁、更小的实现?谢谢!我在PostgreSQL里有一个大表。

postgresql database-indexes
1个回答
0
投票

一个SQL表真的 需要 一个主键。理论上讲,一张表没有主键是没有意义的。(在实践中,一张表的3G行缺少PK是灾难)

在你的情况下, 天然键 似乎是结合了 (gene_id,sample_id,probe_id) 列。这三栏的数值需要用于 独树一帜 value.

问题是你的 if probe is absent; measurement was directly on the gene 反约束.这将禁止一个三列键.删除这个异常将允许一个多列主键.现在,数据技巧是插入一个 虚排 成probe,例如,id=0。

INSERT INTO probe(probe_id, probe_when, probe_name)
 VALUES( 0, '1901-01-01 00:00:00', 'Dummy probe');

现在UPDATE gene_measurements,改变为 probe IS NULLprobe=0.


CREATE TABLE gene_measurements (
  gene INTEGER NOT NULL REFERENCES genes(gene_id) ON DELETE CASCADE
  , sample INTEGER NOT NULL REFERENCES samples(sample_id) ON DELETE CASCADE
  , probe INTEGER NOT NULL REFERENCES probes (probe_id)
  , value REAL NOT NULL
        , PRIMARY KEY ( gene_id, sample_id,probe_id)
);

也许还可以添加一些其他的索引,用不同的顺序,以帮助特定的查询,例如。

CREATE UNIQUE INDEX ON gene_measurements (sample_id,gene_id,probe_id);

你还需要一个支持FK探针的索引,任何以探针为首列的索引都可以。

CREATE INDEX ON gene_measurements (probe_id, ...);

0
投票

你可以在空间和时间之间选择一个任意的阈值。现在,你已经对整张表做了四次索引。这显然会消耗大量的空间。

你可以从索引中删除一些数据,以换取更快的运行时间。

  • 例如,你可以删除 value 的所有索引中。但是,这样一来,除了在索引中进行查找外,对数据的查找也变得很有必要。
  • 你也可以完全删除一些索引。例如,根据你的数据,你可能会删除或者 (sample, gene)(sample, probe). 这就消除了一个完整的数据覆盖,同时仍然允许您使用 sample 部分,适用于有条件的查询 sample 和删除的栏目。同样,你删除的案例就没有之前那么快了。

如果你的目标是实现最小的运行时间 不惜一切代价那么所有这些建议都不适合你。我不认为现在PostgreSQL的世界里有什么可以解决你的问题。

由于你的数据很简单,而且你的用例受到限制,你可以考虑PostgreSQL以外的解决方案。特别是,你基本上只想要一个B-Tree数据结构。(或多个。)有 其他解决方案 来构建这样的数据结构,例如。QDBM. 不过,你还是需要建立多个这样的结构来优化你选择的每种类型。可实现的空间节省我认为不是很高--基本上,你可以摆脱数据,但没有索引。因此,你大概可以节省你当前存储大小的15,但代价是你的软件生态系统的功能受限和额外的复杂性。

你必须决定你需要什么,你想要什么,以及你想为这些目标牺牲什么。考虑到我在这里写下的内容,我会坚持使用PostgreSQL。

© www.soinside.com 2019 - 2024. All rights reserved.