我需要根据特定列中的某些值从表中检索某些行,在示例中名为columnX:
select *
from tableName
where columnX similar to ('%A%|%B%|%C%|%1%|%2%|%3%')
字符串
因此,如果columnX包含指定的值(A,B,C,1,2,3)中的至少一个,我将保留该行。
我找不到比使用类似于的更好的方法。问题是对于一个超过一百万行的表,查询所需的时间太长。
我试着索引它:
create index tableName_columnX_idx on tableName (columnX)
where columnX similar to ('%A%|%B%|%C%|%1%|%2%|%3%')
型
但是,如果条件是可变的(值可以不是A、B、C、1、2、3),则需要为每个条件使用不同的索引。
对于这个问题有没有更好的解决办法?
编辑:谢谢大家的反馈。看起来我已经达到了这一点,也许是因为一个设计错误(主题我已经张贴在一个separated question)。
4条答案
按热度按时间ftf50wuq1#
如果你只想搜索一个字符值的列表,那么把每个字符串拆分成一个字符数组,并对数组进行索引:
字符串
然后搜索索引:
型
xmq68pz92#
我同意Quassnoi,GIN index是最快和最简单的-除非写性能或磁盘空间是问题,因为它占用了大量的空间,并增加了
INSERT
,UPDATE
和DELETE
的成本。我的补充回答是由你的声明引发的:
我找不到比使用
similar to
更好的方法。如果这就是你发现的,那么你的搜索还没有结束。
SIMILAR TO
是 * 完全浪费时间 *。从字面上看,Postgres只是为了遵守(奇怪的)SQL标准而包含它。检查EXPLAIN ANALYZE
的查询输出,您会发现SIMILAR TO
已被正则表达式替换。在内部,每个
SIMILAR TO
表达式都被重写为正则表达式。因此,对于每一个SIMILAR TO
表达式,至少有一个正则表达式匹配快一点。EXPLAIN ANALYZE
为您翻译,如果您不确定。你不会在手册中找到这一点,PostgreSQL并不承诺这样做,但我还没有看到一个例外。进一步阅读:
ctrmrzij3#
我认为这是一个数据建模问题。您似乎将
text
字段用作集合,存储单个字符代码以标识集合中存在的值。如果是这样,我想使用以下方法之一重新构建此表:
columnX
,并将其替换为一个新表,该表具有指向tableName(id)
的外键引用和一个charcode
列,该列每行包含一个来自旧columnX
的字符,如CREATE TABLE tablename_columnx_set(tablename_id integer not null references tablename(id), charcode "char", primary key (tablename_id, charcode))
。然后可以使用普通的SQL子查询、连接等相当有效地搜索columnX
中的键。如果您的应用程序无法科普这种变化,您可以始终保留columnX
并使用触发器维护侧表。columnX
转换为具有虚拟值的hstore
关键帧。然后可以使用hstore操作符,如columnX ?| ARRAY['A','B','C']
。columnX
的hstore上的GiST
索引应该为这些操作提供相当可靠的性能。columnX
转换为整数数组,使用intarray
和Intarray GiST索引。有一个Map表的代码,以整数或转换的应用程序。时间允许的话,我会跟进每个演示。制作虚拟数据是一件痛苦的事情,所以这取决于其他情况。
oymdgrw74#
我会把这个作为答案,因为它可能会在未来指导其他人:为什么不使用6列
haveA
,haveB
~have3
,并执行6部分OR
查询?还是使用位掩码?如果有太多的属性而无法为每个属性分配一列,我可以尝试创建一个“属性”表:
字符串
让DBMS去操心优化的事。