使用PostgreSQL,我有一个包含以下4个属性的大约2.5亿行的非常大的表:
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查询根据定义的sim_value
和word1
选择word2
属性:
(假设我有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)
平均需要1~1.5分钟才能返回真正很长的sim_value
!将整个表存储在内存中非常昂贵,因为它的重量超过10 GB。
如何加快此查询?你有什么建议吗?
PS:word1
和word2
永远不会相同,所以如果是1个案例:word1
是X 而 word2
是Y,那么那里不存在word1
为Y 且 word2
为X的另一行!
注意:我搜索了类似的主题,但没有一个解决了这个问题。感谢您的理解
谢谢
答案 0 :(得分:4)
首先,如果您还没有,我会确保存在以下索引:
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'
答案 1 :(得分:2)
所以你必须在这两个字段上创建索引
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')
答案 2 :(得分:0)
从不开始存储字,但仅引用,这将使桥接表更精简:
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
;
(或使用视图来模拟旧表)
检查这个较旧的答案,了解表中squeezing out脂肪重复列的配方。