2016-11-21 66 views
1

使用full_name列和状态列设置多列索引的最佳方法是什么?搜索将使用确切的状态,并在full_name列中进行部分搜索。查询会这样:如何通过部分字段搜索正确构造多列索引

WHERE full_name ~* 'jones' AND state = 'CA'; 

搜索大约2000万条记录。

谢谢!

约翰

回答

0

该状态看起来非常直截了当 - 正常的索引应该足够了。就全名搜索而言,这是一项很多工作,但拥有2000万条记录,我认为股息将为自己说话。

创建您的表作为的tsvector一个新的领域,并将其命名为full_name_search这个例子的目的:

alter table <blah> add column full_name_search tsvector; 

执行列初始群体:

update <blah> 
set full_name_search = to_tsvector (full_name); 

如果可能的话,使该字段不可空。

创建触发器,每当它的更新是现在会自动填充此字段:

create trigger <blah>_insert_update 
before insert or update on <blah> 
for each row execute procedure 
    tsvector_update_trigger(full_name_search,'pg_catalog.english',full_name); 

在新字段添加一个索引:

create index <blah>_ix1 on <blah> 
using gin(full_name_search); 

从这里出发,重新构建查询,以便对搜索tsvector字段替代文本字段:

WHERE full_name_search @@ to_tsquery('jones') AND state = 'CA'; 

您可以缩短(例如,不要创建额外的字段,而是使用基于函数的索引来代替),它会为您提供改进的性能,但不如您可以获得的那样好。

一个警告 - 我认为to_tsvector将拆分为基于内容的逻辑中断向量分量,所以这样的:

Catherine Jones Is a Nice Lady 

将正常工作,但这样的:

I've been Jonesing all day 

可能惯于。

+0

我不认为你实际上需要将'full_name_search'列添加到表中。你可以直接在'to_tsvector(full_name)'上创建一个索引 –

+0

@a_horse_with_no_name - 我可能是错的,但是我在某一时刻对两者进行了基准测试,当我将它作为一个单独的字段时,速度明显更快。这可能会随后发布而改变,也可能我错了。 – Hambone

+0

约翰 - 我建议你尝试两种。我很想看看添加该字段是否值得与否。 – Hambone