我需要从表中检索某些行,具体取决于特定列中的某些值,在示例中名为 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发布的主题)。答案 0 :(得分:3)
如果您只想搜索单字符值的列表,则将每个字符串拆分为一个字符数组并索引该数组:
CREATE INDEX
ix_tablename_columnxlist
ON tableName
USING GIN((REGEXP_SPLIT_TO_ARRAY(columnX, '')))
然后搜索索引:
SELECT *
FROM tableName
WHERE REGEXP_SPLIT_TO_ARRAY(columnX, '') && ARRAY['A', 'B', 'C', '1', '2', '3']
答案 1 :(得分:1)
我会将此作为答案发布,因为它可能在将来指导其他人:为什么不有6列,haveA
,haveB
〜have3
并执行6部分OR
查询?或者使用位掩码?
如果每个属性分配的属性太多,我可能会尝试创建一个“属性”表:
(fkey, attr) VALUES (1, 'A'), (1, 'B'), (2, '3')
让DBMS担心优化问题。
答案 2 :(得分:1)
我同意@Quassnoi,GIN index是最快最简单的 - 除非写入性能或磁盘空间是问题,因为它占用了大量空间并且为INSERT
吃了相当多的性能,{ {1}}和UPDATE
。
我的补充答案由你的陈述引发:
DELETE
如果这是你找到的,那么你的搜索还没有结束。 I can't find a better approach than using similar to.
完全浪费时间。从字面上看。 PostgreSQL只是为了符合(奇怪的)SQL标准。检查SIMILAR TO
的输出以查找您的查询,您会发现EXPLAIN ANALYZE
已被正则表达式替换。
在内部,每个SIMILAR TO
表达式都被重写为正则表达式。因此,对于每个SIMILAR TO
表达式,至少有一个正则表达式匹配更快一些。如果您不确定,请SIMILAR TO
为您翻译。你不会在手册中找到这个,PostgreSQL不承诺这样做,但我还没有看到异常。
此related answer on dba.SE中的详细信息。
答案 3 :(得分:1)
这让我觉得这是一个数据建模问题。您似乎使用text
字段作为集合,存储单个字符代码以标识集合中存在的值。
如果是这样,我想重新构建此表以使用以下方法之一:
标准关系规范化。删除columnX
,并将其替换为新表,其中包含对tableName(id)
的外键引用和charcode
列,其中包含每行旧columnX
中的一个字符,例如{ {1}}。然后,您可以使用普通的SQL子查询,连接等在CREATE TABLE tablename_columnx_set(tablename_id integer not null references tablename(id), charcode "char", primary key (tablename_id, charcode))
中相当有效地搜索密钥。如果您的应用程序无法应对该更改,您可以始终保留columnX
并使用触发器维护边表。
使用虚拟值将columnX
转换为columnX
个键。然后,您可以使用hstore
之类的hstore运算符。 columnX ?| ARRAY['A','B','C']
的hstore上的GiST
索引应该为这些操作提供相当可靠的性能。
如果您的表格更改率较低且您可以支付GIN索引的费用,则拆分为数组as recommended by Quassnoi;
将columnX
转换为整数数组,使用columnX
和intarray GiST索引。有一个代码映射表到整数或在应用程序中转换。
时间允许我会跟进每个人的演示。弥补虚拟数据是一件痛苦的事情,因此它将取决于其他方面的情况。