此查询查找域的后缀:
SELECT
DISTINCT ON ("companyDomain".id)
"companyDomain".domain,
"publicSuffix".suffix
FROM
"companyDomain"
INNER JOIN
"publicSuffix"
ON
REVERSE("companyDomain".domain) LIKE REVERSE("publicSuffix".suffix) || '%'
ORDER BY
"companyDomain".id, LENGTH("publicSuffix".suffix) DESC
编辑:注意这也适用于子域。
你可以在这里摆弄这个例子,并用pev可视化这个计划。我尝试过向表中添加覆盖索引,但查询规划器最终没有使用它们。也许还有另一个查询更有效?
4条答案
按热度按时间n1bvdmb61#
你考虑过使用
gin
索引?我对您的示例dml进行了以下修改:
下面是查询计划:
作为奖励-你甚至不需要
REVERSE()
索引和查询中的文本:查询所用时间相同,但仍使用gin索引:
ps:我猜你只需要一个索引-在这种情况下:
companyDomain_domain_reverse
tpxzln5u2#
索引对数据结构/查询没有任何好处。试想一下索引在这里是如何使用的。我运气不好。
我的建议是将域/后缀转换为数组,如
让我们比较这些查询:
据我所知,这里的瓶颈,
Rows Removed by Join Filter: 8093814
似乎postgresql构建了表的笛卡尔连接,然后使用ON
条件:要解决此问题,请尝试使用数组运算符:
它可能不太准确(例如
aaa.bbb
等于bbb.aaa
这里)但是你可以把它修好WHERE
条款。无论如何它会更快。就目前而言
domain
以及suffix
列是多余的,因为您可以从中恢复它们adomain/asuffix
使用array_to_string(anyarray, text [, text])
功能。另一种方法是,为了避免表结构中的更改,可以在上创建函数索引
string_to_array()
然后在过滤器/连接中使用它。dxxyhpgq3#
你想要这样的比赛吗
但是您知道postgresql不会为此使用索引,因为模式字符串以通配符开头。所以你把这两条线颠倒过来:
并在上创建函数索引
REVERSE("companyDomain".domain)
.这是一个非常好的主意,但是postgresql不使用您的索引。这是因为dbms不知道字符串中的内容(因为这是表数据,dbms不会先读取整个表来获得计划)。在最坏的情况下,所有颠倒的后缀都以
'%'
. 在这种情况下,如果dbms决定遍历索引,这可能会非常慢。你知道后缀不是以'%'
,但dbms不这样做,而是决定一个安全的计划(全表扫描)。这里有记录:https://www.postgresql.org/docs/9.2/indexes-types.html
优化器还可以使用b-树索引来查询涉及模式匹配运算符的查询,如和~如果模式是常量。。。
我认为没有办法说服postgresql使用索引是安全的。
AND REVERSE("publicSuffix".suffix) || '%' NOT LIKE '/%%' ESCCAPE '/'
举个例子,没用。在我看来,你最好的办法是使用索引
RIGHT(domain, 3)
以及RIGHT(suffix, 3)
,因为我们知道包含点的后缀至少有三个字符长。这可以缩小匹配范围,使其足够有用。演示:https://www.db-fiddle.com/f/dppvfwjpvjhyfnvut4k7ws/1
ou6hu8tu4#
怎么样:
我们得到第一个的位置
.
在域中,然后使用该值的负值(+1)包含第一个.
)从…中提取后缀RIGHT
向左。看起来它跑得更快,从2500毫秒到120毫秒。
带电试验