假设我有一个表,其中包含许多称为comments
的记录,并且每个记录仅包含一个文本主体:
CREATE TABLE comments(id INT NOT NULL, body TEXT NOT NULL, PRIMARY KEY(id));
INSERT INTO comments VALUES (generate_series(1,100), md5(random()::text));
现在,我有一个输入数组,其中包含N个子字符串,并且具有任意长度。例如:
abc
xyzw
123456
not_found
对于每个输入值,我想返回符合特定条件的所有行。
例如,假设该表包含以下记录:
| id | body |
| -- | ----------- |
| 11 | abcd1234567 |
| 22 | unkown12 |
| 33 | abxyzw |
| 44 | 12345abc |
| 55 | found |
我需要一个返回以下结果的查询:
| substring | comments.id | comments.body |
| --------- | ----------- | ------------- |
| abc | 11 | abcd1234567 |
| abc | 44 | 12345abc |
| xyzw | 33 | abxyzw |
| 123456 | 11 | abcd1234567 |
到目前为止,我有这个SQL查询:
SELECT substrings, comments.id, comments.body
FROM unnest(ARRAY[
'abc',
'xyzw',
'123456',
'not_found'
]) AS substrings
JOIN comments ON comments.id IN (
SELECT id
FROM comments as inner_comments
WHERE inner_comments.body LIKE ('%' || substrings || '%')
);
但是数据库客户端卡住了超过10分钟。我缺少有关联接的信息吗?
请注意,这是我的问题的简化示例。我当前对注释的检查不是LIKE
语句,而是具有不同功能(模糊匹配)的复杂开关案例语句。
答案 0 :(得分:1)
使用IN
绕行是不必要的,除非优化程序可以重写它,而且可能无法重写,否则会增加开销。如果没有,那就试试看。
SELECT un.substring,
comments.id,
comments.body
FROM unnest(ARRAY['abc',
'xyzw',
'123456',
'not_found']) un (substring)
INNER JOIN comments
ON comments.body LIKE ('%' || un.substring || '%');
但是由于开头是通配符,因此仍不能在此处使用索引。您可能需要查看Full Text Search,并查看可以使用哪些选项来改善情况。
答案 1 :(得分:0)
基本上,您正在最有可能没有FULLTEXT索引的列中执行FULLTEXT搜索。
您可以尝试的第一步是为“正文” FULLTEXT列建立索引。查看详细信息here,然后使用CONTAINS执行搜索,但是老实说,由于您要执行模糊匹配,因此您不能依靠SQL Server来执行搜索-这样就无法正常工作。您将需要索引服务,例如ElasticSearch,CloudSearch,Azure Search等