是否可以在连接字段的非重叠前缀时避免嵌套循环连接?

时间:2013-05-11 21:42:40

标签: sql postgresql

我有一个QSO(无线电联系)记录数据库,我想按车站国家汇总。该国家/地区源自电台呼号的前缀,由ITU Prefix List

定义

不幸的是,这个前缀的长度可变。例如,以W开头的所有内容都分配给美国,但大多数国家/地区都由一个或多个双字符前缀标识。有些需要3个字符的前缀,例如,3DA到3DM是斯威士兰,但3DN到3DZ是Fidji。

我可以像这样构建一个表:

CREATE TABLE country (
    prefix varchar(3) primary key,
    country varchar(10)
);

并使用相当丑陋的表达式执行简单连接:

SELECT * from qso
INNER JOIN country
ON left(qso.callsign, length(country.prefix)) = country.prefix

可以理解,这使用嵌套循环执行连接。这是有道理的,因为没有额外的知识,我的国家/地区表中的前缀不会重叠,这个连接可以返回几个国家的单一QSO。

现在,我可以使用一个丑陋的黑客,并在我的prefix表中插入所有显式的3字符前缀,并使用相等的连接。这会使我的前缀表的大小增加150倍,但自然允许使用哈希或合并连接。

但是,我的前缀不重叠​​,并且QSO已经被callign索引,因此有一种明显有效的类似合并的算法来执行此连接。

有没有办法让Postgres加入我想到的连接算法?也许使用花式索引类型或特殊匹配运算符?

注意:QSO表类似于:

CREATE TABLE qso (
    time_on timestamp primary key,
    callsign varchar(10),
    ...
);
CREATE INDEX qso_callsign ON qso(callsign);

2 个答案:

答案 0 :(得分:1)

执行此操作似乎是一种正确的方法是使用CREATE OPERATOR定义自定义前缀匹配函数,并通过MERGES子句将其标记为可合并。当我测试这确实有效时,我会编辑这个答案。

另一种可能是使用有限的子选择来查找小于呼号的“最大”前缀,如自然归类顺序所定义的那样 - 可能更自然。

答案 1 :(得分:0)

我认为最好的办法是将所有三个字符的前缀添加到country表中。我不知道这会如何增加“150倍”。假设代码有26个大写字符和10个数字,这最多会增加36倍。但是,大多数代码可能没有国家,因此数量会少得多 - 只是实际分配给国家的3字符代码的数量。

另一种选择是做两个这样的连接:

select qso.*, coalesce(c3.whatever, c2.whatever) -- use the c3 version first, then the c2 version
from qso left outer join
     country c2
     ON left(qso.callsign,2) = c2.prefix left outer join
     country c3
     on left(qso.callsign, 3) = c3.prefix;

这些联接应该使用country表上的索引。如果你将它封装在一个视图中,那么其他代码就可以使用它。