SQL选择包含文本字段中子字符串的行

时间:2014-02-17 15:01:28

标签: sql postgresql pattern-matching

我有CLIENTS_WORDS表,其中包含列:ID,CLIENT_ID,Postgresql数据库中的WORD

ID|CLIENT_ID|WORD
1 |1242     |word1
2 |1242     |WordX.foo
3 |1372     |nextword
4 |1999     |word1

在此表中可能有大约100k-500k行 我有这样的查询字符串:

'Some people tell word1 to someone'
'Another stringWordX.foo too possible'

我希望从查询字符串中包含WORD列文本的表中选择* 现在我使用select

select * from CLIENTS_WORDS
where strpos('Some people tell word1 to someone', WORD) > 0

我的问题是,检索匹配行的最佳性能/快速方法在哪里?

1 个答案:

答案 0 :(得分:4)

使用unnest()和JOIN可以获得更好的效果。像这样:

SELECT DISTINCT c.client_id
FROM   unnest(string_to_array('Some people tell word1 ...', ' ')) AS t(word)
JOIN   clients_words c USING (word);

查询的详细信息取决于您的要求缺失细节。这是将字符串拆分为 space 字符。

更灵活的工具将是regexp_split_to_table(),您可以在其中使用character classes or shorthands作为分隔符字符。像:

regexp_split_to_table('Some people tell word1 to someone', '\s') AS t(word)
regexp_split_to_table('Some people tell word1 to someone', '\W') AS t(word)

当然,列clients_words.word需要为性能编制索引:

CREATE INDEX clients_words_word_idx ON clients_words (word)

会很快。

忽略单词边界

如果你想完全忽略单词边界,那么整个问题就会变得更加昂贵。我会想到LIKE / ILIKE与三元组GIN索引相结合。详情:
PostgreSQL LIKE query performance variations

或其他模式匹配技术 - 回答dba.SE:
Pattern matching with LIKE, SIMILAR TO or regular expressions in PostgreSQL

但是,您的案例向后,索引无济于事。您必须检查每一行的部分匹配 - 使查询非常昂贵。优越的方法是反向操作:拆分词和然后搜索。