我想知道联合是否会以与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')
答案 0 :(得分:2)
union
的运行速度与where
子句的运行速度相同。 union
会导致删除重复项的开销,这通常意味着对数据进行排序。这就是为什么最好使用union all
的原因,因为它可以达到相同的结果集。
也就是说,有时候union
/ union all
中使用的子查询比在or
或where
中使用on
的相同查询可以更好地进行优化。条款。
因此,不可能说union
在这种情况下总是不好的。合理的观点是union
会产生额外的开销。如果可以优化子查询,则此开销可能并不重要,但通常union
会降低性能。
答案 1 :(得分:0)
只是为了补充我认为很出色的戈登的答案,根据经验,UNION
(或UNION ALL
)将需要遍历表(或表的索引)以检索表的每个子集行合并之前。
另一方面,单个WHERE
将需要对表(或其索引)进行一次遍历以产生相同的结果。
答案 2 :(得分:0)
Where子句过滤查询,而Union追加并聚集多个查询。在大多数(如果不是全部)情况下,Where子句比完成同一件事的两个where的并集要快。
如果不能立即清除,下面是两个图像,用于pgAdmin中的explain / analyze比较。
上图说明了Union操作。看看如何对表格进行两次扫描?
现在观察下图:
简单得多,您不觉得吗?因为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(...)
表达式,但是机制是相同的。 (最困难的部分是避免表达式的重复...)