快速中缀搜索并依靠4000万行表postgresql

时间:2014-09-10 10:45:04

标签: performance postgresql case

我是数据库管理的新手,但我需要创建一个数据库视图,而db admin要求它在5分钟或更短的时间内运行。我的数据库是RedHat4.4 linux 64位上的PostgreSQL 9.1.1。我不确定硬件规格。其中一个表是4000万行。从表中,我有一列目录路径,我必须从中分组大约20个字符串模式并计算其出现次数。字符串模式需要中缀搜索,因为它可能位于路径的中间或末尾。字符串模式也有一个优先级,如%str1%然后' str1',%str2%然后' str2',str1,str2,str3等都可以发生在相同的路径,即

path 
/usr/myblock/str1/str2
/usr/myblock/something/str2
/usr/myblock/str1/something/str3

到目前为止,我所做的是用CASE语句构建一个表,然后通过LIKE将它连接回原始表,然后选择SELECT id,pattern,count(pattern)。查询运行时很糟糕,花了5分钟从5.5K行检索。我的查询如下:

WITH a AS (
SELECT CASE 
WHEN path ~ '^/usr/myblock/(.*)str1(.*)' THEN 'str1'
WHEN path ~ '^/usr/myblock/(.*)str2$' THEN 'str2'
WHEN path ~ '^/usr/myblock/(.*)str3$' THEN 'str3'
.... --multiple other case conditions
WHEN path ~ '^/usr/myblock/' THEN 'others'
ELSE 'n/a'
END as flow
FROM mega_t WHERE left(path,13)='/usr/myblock/' limit 5)
SELECT id, a.flow, count(*) AS flow_count FROM a 
JOIN mega_t ON path LIKE '%' || a.flow || '%'
WHERE (some_conditions) AND to_timestamp(test_runs.created_at::double precision) 
> ('now'::text::date - '1 mon'::interval) --collect last 1 month's results only
GROUP BY id, a.flow;

我对这个简单案例的预期输出是:

id | flow | flow_count
1  | str1 | 2
2  | str2 | 1

有什么更好的方法来搜索这样的子串并计算出现次数?我不能使用ts_stat,也不能使用SELECT count(path)WHERE路径LIKE%str1%'因为它需要if-else优先级。我读过有关创建三元组索引的内容,但我认为这对我的模式来说太过分了。我希望这个问题清楚有用。我应该补充的另一件事是,每隔几秒钟或几分钟就会频繁更新4000万行表,而每天每八小时访问一次。

0 个答案:

没有答案