使用A联盟B的Postgres性能与A或B的位置

时间:2018-08-16 00:11:29

标签: sql postgresql

我想知道联合是否会以与where子句相同的速度运行。

注意:我确实将索引放在任何相关列上

例如

-- Using where or condition
select group, name from jobs where group = 'a' or group = 'b'

-- Using union's to achieve the same result
select group, name from jobs where group = 'a'
union
select group, name from jobs where group = 'a'

在上面的示例中,有一种技术会更快吗?还是它们都以相同的速度执行

我问的原因是我需要使用similarity, trigrams or ts_vectors进行模糊匹配,其中需要返回实际匹配的过滤条件,以便我知道如何找到特定的行。

例如

-- Using where or condition
select description from jobs where 
    description = to_tsvector('english', description) @@ to_tsquery('english', 'ability <-> to <-> motivate <-> others')
    or
    description = to_tsvector('english', description) @@ to_tsquery('english', 'excellent <-> organisational <-> skills')

-- NOTE: When using (where OR) I have no way of telling which condition actually matched 

-- Using union's to achieve the same result
select 'ability to motivate others' as search_term, description
 from jobs
 where description = to_tsvector('english', description) @@ to_tsquery('english', 'ability <-> to <-> motivate <-> others')
union
or
select 'excellent organisational skills' as search_term, description
from jobs
where description = to_tsvector('english', description) @@ to_tsquery('english', 'excellent <-> organisational <-> skills')

4 个答案:

答案 0 :(得分:2)

union的运行速度与where子句的运行速度相同。 union会导致删除重复项的开销,这通常意味着对数据进行排序。这就是为什么最好使用union all的原因,因为它可以达到相同的结果集。

也就是说,有时候union / union all中使用的子查询比在orwhere中使用on的相同查询可以更好地进行优化。条款。

因此,不可能说union在这种情况下总是不好的。合理的观点是union会产生额外的开销。如果可以优化子查询,则此开销可能并不重要,但通常union会降低性能。

答案 1 :(得分:0)

只是为了补充我认为很出色的戈登的答案,根据经验,UNION(或UNION ALL)将需要遍历表(或表的索引)以检索表的每个子集行合并之前。

另一方面,单个WHERE将需要对表(或其索引)进行一次遍历以产生相同的结果。

答案 2 :(得分:0)

Where子句过滤查询,而Union追加并聚集多个查询。在大多数(如果不是全部)情况下,Where子句比完成同一件事的两个where的并集要快。

如果不能立即清除,下面是两个图像,用于pgAdmin中的explain / analyze比较。 enter image description here

上图说明了Union操作。看看如何对表格进行两次扫描?

现在观察下图:

enter image description here

简单得多,您不觉得吗?因为postgres只需要扫描一次数据,然后过滤结果集,那么简单的where子句的运行就更加顺畅。

对于其他问题,您可以尝试使用分组,条件匹配或子选择,尽管所有这些方法都将略微增加计算时间(在子选择的情况下,可能会消除不使用联合而获得的优势) ,具体取决于您的数据结构。

答案 3 :(得分:0)

诀窍是枚举(并记住)匹配的条件。 带有文本字段而不是ts_vector的简化示例:


\i tmp.sql

create table persons( id serial primary key, hair text, eyes text);

insert into persons( hair , eyes)  VALUES
 ( 'blonde', 'blue' ) , ( 'blonde', 'brown' ) , ( 'blonde', 'green' )
, ( 'brown', 'blue' ) , ( 'brown', 'blue' ) , ( 'brown', 'green' )
, ( 'red', 'brown' ) , ( 'red', 'blue' ) , ( 'red', 'green' )
        ;


SELECT p.*
        , x.redhaired,x.blueeyed
FROM persons p
JOIN (SELECT q.id
        -- set flags for matched conditions
        , case when hair = 'red' THEN True else False end AS redhaired
        , case when eyes = 'blue' THEN True else False end AS blueeyed
        FROM persons q
        WHERE q.hair = 'red' OR q.eyes = 'blue' -- <<-- composite search-clause
        ) x ON x.id = p.id -- rejoin on PK
        ;

您可能希望选择一些case ...字符串距离度量值,而不是布尔ts_xxx(...)表达式,但是机制是相同的。 (最困难的部分是避免表达式的重复...)