加快大型 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 基于定义的 word1
和 word2
的 sim_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.: word1
和 word2
永远不相同,所以如果对于 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 中 脂肪重复列的配方。
使用 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 基于定义的 word1
和 word2
的 sim_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.: word1
和 word2
永远不相同,所以如果对于 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 中