我有一个网址表(域名和网页)
URLs
-----
url_id
url
我有一个域名列表,我想看看它是否包含在URL表中。
所以,如果我的列表中有域名: http://stackoverflow.com
我希望它匹配以下URL:url记录:
https://stackoverflow.com/question/230479
https://stackoverflow.com/question/395872364
等
URL表非常大,1000万+并且会增长
我想测试的域名列表将在1-10k
之间变化目前我正在创建域列表的临时表,然后加入URL表以查找匹配的所有URL
SELECT * from URLs
JOIN tmp_table_domains on tmp_table_domain.domain like URLs.url || '%'
我已经将URL.url和tmp_table_domain.domain编入索引,并认为索引将在外卡的右侧工作。
但是,EXPLAIN ANALYZE不显示正在使用的任何索引。一篇帖子中提到postgres 8.x不能像索引一样加入,但是我找不到任何其他方法来支持这个或替代方案,或者它是否适用于更新的版本
如果有帮助,我的帖子是9.1。如果升级会解决这个问题,那很好,只有没有升级的理由没有任何理由让我知道
Edit_1 这是第一个已经开展工作的数据库项目,我正在学习这一切
我不介意删除所有上述内容并使用更好的方法,无论是临时表/数组/更好的查询
edit_2
GroupAggregate (cost=1429152.90..1435118.48 rows=340890 width=44) (actual time=157905.450..157905.609 rows=27 loops=1)
-> Sort (cost=1429152.90..1430005.13 rows=340890 width=44) (actual time=157905.425..157905.451 rows=29 loops=1)
Sort Key: task_items.task_item
Sort Method: quicksort Memory: 29kB
-> Nested Loop (cost=14210.95..1387337.41 rows=340890 width=44) (actual time=18216.187..157905.055 rows=29 loops=1)
Join Filter: ((task_items.task_item)::text ~~ ((tmp_domains.domain)::text || '%'::text))
-> Hash Join (cost=14210.95..194126.53 rows=14066 width=44) (actual time=452.262..7953.639 rows=13737 loops=1)
Hash Cond: (task_items.task_id = tasks.task_id)
-> Seq Scan on task_items (cost=0.00..170062.71 rows=2589924 width=48) (actual time=0.019..4480.360 rows=2575206 loops=1)
Filter: (task_item_status_id = 2)
-> Hash (cost=14205.68..14205.68 rows=421 width=4) (actual time=440.409..440.409 rows=171 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 7kB
-> Seq Scan on tasks (cost=0.00..14205.68 rows=421 width=4) (actual time=101.491..439.821 rows=171 loops=1)
Filter: ((account_detail_id = 695) AND (base_action_type_id <> ALL ('{1,3,4}'::integer[])))
-> Materialize (cost=0.00..109.70 rows=4847 width=32) (actual time=0.002..4.924 rows=4536 loops=13737)
-> Seq Scan on tmp_domains (cost=0.00..85.47 rows=4847 width=32) (actual time=0.010..5.851 rows=4536 loops=1)
Total runtime: 157907.403 ms
实际查询与上面的简化说明略有不同。
task_items的行数不到700万 并且tmp_domains有4,500
总结一下。将字符串列表部分匹配到列的最佳方法是什么
答案 0 :(得分:0)
几个月前,Peter Eisentraut发表了pguri
extension,这可以大大简化你的工作。它目前只是源代码,因此您必须构建库代码,这在任何Linux机器上都非常容易,然后将文件放在PG安装目录中,最后放在数据库中CREATE EXTENSION
。之后,您可以执行简单的查询,例如:
SELECT *
FROM urls
JOIN tmp_table_domains d ON uri_host(d.domain::uri) = uri_host(urls.url::uri);
请注意,这也会在不同的方案之间匹配,因此http://
域将匹配相应的https://
网址。如果您不想这样做,那么还要加入uri_scheme()
域名和网址。
索引将适用于扩展函数返回的text
数据类型。如果您的数据库使用UTF-8
编码,您应该像这样创建索引:
CREATE INDEX url_index ON urls (uri_host(url::uri) text_pattern_ops);
然后还有你的域名表。
你可以ALTER TABLE urls ALTER COLUMN url SET DATA TYPE uri
这样你可以放弃演员。