加快大型 PostgreSQL 数据库(2.5 亿行)中的 SELECT 查询响应

Speeding up SELECT query response in large PostgreSQL Database (250 million rows)

使用 PostgreSQL,我有一个非常大的 table 约 2.5 亿行,由以下 4 个属性组成:

CREATE TABLE public.sim_values_english
(
  id bigint NOT NULL DEFAULT nextval('sim_values_english_id_seq'::regclass),
  word1 character varying(255),
  word2 character varying(255),
  sim_value double precision,
  CONSTRAINT pk_sim_values_english PRIMARY KEY(id)
)

我正在尝试 select 基于定义的 word1word2sim_value 属性,使用以下 SELECT 查询:

(假设我有 2 个词:X 和 Y,其中 X 或 Y 可以属于 word1 或 word2)

SELECT sim_value
From public.sim_values_english
Where (word1='X' or word2='X') and (word1='Y' or word2='Y') and (word1!=word2)

这 return 平均需要 1~1.5 分钟,sim_value 真的很长!将整个 table 存储在内存中非常昂贵,因为它的重量超过 10 GB)。

我怎样才能加快这个查询?你有什么建议?

P.S.: word1word2 永远不相同,所以如果对于 1 种情况:word1 是 X word2是Y,则不存在另一行word1是Y word2是X!

注意:我搜索过类似的主题,但其中 none 解决了这个问题。感谢理解

谢谢

首先,如果您还没有,我会确保以下索引存在:

CREATE INDEX ON sim_values_english(word1, word2);

然后我会尝试以下查询:

SELECT sim_value
FROM sim_values_english
WHERE word1='X' AND word2='Y'
UNION ALL
SELECT sim_value
FROM sim_values_english
WHERE word1='Y' AND word2='X'

所以你必须在这两个字段上创建索引

CREATE INDEX word1_word2_idx ON sim_values_english (word1, word2);

那么你的查询很基础

SELECT sim_value
FROM sim_values_english
WHERE (word1='X' AND word2='Y') OR (word1='Y' AND word2='X')

存储 单词 开始,但仅 引用 到它们,这将使桥梁-table更精简:

CREATE TABLE words_english
        ( word_id integer -- or: serial if you want
                NOT NULL PRIMARY KEY
        , word varchar UNIQUE
        );

CREATE TABLE sim_values_english
        ( word_id integer NOT NULL references words_english (word_id)
        , other_id integer NOT NULL references words_english (word_id)
        , sim_value DOUBLE PRECISION NOT NULL DEFAULT 0.0
        , PRIMARY KEY (word_id, other_id)
        );

CREATE UNIQUE INDEX ON sim_values_english(other_id,word_id);

您的查询现在可以改写为:

SELECT sim_value
FROM sim_values_english v
JOIN words_english one ON v.word_id = one.word_id
JOIN words_english two ON v.other_id = two.word_id
WHERE one.word IN ('X' ,'Y')
AND two.word IN ( 'X', 'Y' )
AND v.word_id <> v.other_id
        ;

(或使用视图模拟旧的 table)

检查这个较旧的答案,以获取 table 中 脂肪重复列的配方。