但是在示例中,第一个查询的条件为column a
,而第二个查询的条件为column b
。这可能来自难以优化的查询:
SELECT * FROM mytable WHERE a=X OR b=Y
使用简单的B树索引很难优化此查询。引擎是否在列上搜索索引a
?还是列上b
?无论哪种方式,搜索其他术语都需要进行表格扫描。
因此,使用UNION可以将两个查询分开为一个查询的技巧。每个子查询可以为每个搜索词使用最佳索引。然后使用UNION合并结果。
但是,这两个子集可能会重叠,因为某些行b=Y
也可能同时存在,a=X
在这种情况下,这两个行都出现在两个子集中。因此,您必须进行重复消除,否则在最终结果中将看到一些行两次。
SELECT * FROM mytable WHERE a=X
UNION DISTINCT
SELECT * FROM mytable WHERE b=Y
UNION DISTINCT
之所以昂贵,是因为典型的实现对行进行排序以查找重复项。就像您使用一样SELECT DISTINCT ...
。
我们还认为,如果您要合并的行的两个子集在两个子集中都有很多行,那么它的工作就更加“浪费”了。有很多行要消除。
但是,如果可以保证两组行已经不同,则无需消除重复项。也就是说,如果您保证没有重叠。如果您可以依靠它,那么消除重复将永远是绝妙的选择,因此查询可以跳过该步骤,从而跳过代价高昂的排序。
如果您更改查询以确保它们选择行的不重叠子集,那将是双赢。
SELECT * FROM mytable WHERE a=X
UNION ALL
SELECT * FROM mytable WHERE b=Y AND a!=X
保证这两个集合没有重叠。如果第一个集合的行在哪里a=X
,第二个集合的行在哪里a!=X
,则两个集合中都不能有行。
因此,第二个查询仅捕获where中的 某些 行b=Y
,但捕获a=X AND b=Y
第一组中已经包含的任何行。