使用联合而不是OR

有时可以通过稍微修改查询来解决慢速查询。 当使用OR或IN运算符在WHERE子句中比较多个值时,可以说明一个这样的示例。 通常,OR可能会导致索引或表扫描,就I / O消耗或总体查询速度而言,这可能不是首选的执行计划。

查询优化器创建执行计划时,许多变量会起作用。 这些变量包括许多硬件特征,实例设置,数据库设置,统计信息(表,索引,自动生成)以及编写查询的方式。 在这里,我们更改了编写请求的方式。 无论这看起来有多么意外,即使两个不同的查询可以返回相同的结果,根据查询的格式,它们遵循的路径也可能完全不同。

联盟vs或


根据我在SQL Server方面的大部分经验,OR通常不如UNION高效。 OR经常发生的情况是它经常引起扫描。 在某些情况下,这有时可能是最好的方法,我将其保留在单独的文章中,但是总的来说,我发现当大量条目受到影响时,这是速度变慢的主要原因。 因此,让我们开始进行比较。

这是我们的OR语句:

SELECT SalesOrderID, * FROM sales.SalesOrderDetail WHERE ProductID = 750 OR ProductID = 953 



从该执行计划中,我们看到我们正在扫描121,000行。 (您看不到行数,但是是)。

现在我们执行相同的查询,但是使用UNION而不是OR编写:

 SELECT [SalesOrderID], * FROM sales.SalesOrderDetail WHERE ProductID = 750 UNION SELECT [SalesOrderID], * FROM sales.SalesOrderDetail WHERE ProductID = 953 



在这里,我们看到了两个操作分支。 一个分支影响358行,其他346条影响。 发现两个分支都执行合并两组结果的串联操作。 我们有两个单独的搜索,但是我们也有一个键搜索以获取所需的SELECT列表。 这对于扫描操作不是必需的,因为我们仍然会影响扫描操作中的所有行,因此数据是在扫描期间而不是之后获得的。 这是由于我们需要索引和行,而不是UNION或OR。 但是,我会说选择也是选择搜索还是扫描的一个因素,但是在本文中我们将忽略它。

解说


为什么UNION引起更多搜索而不是扫描的原因,因为每个操作必须满足一定的选择性要求才能符合搜索条件。 (选择性是特定过滤列的唯一性)。 OR在单个操作中发生,因此,如果将每列的选择性合并在一起并且超过一定百分比,则认为扫描效率更高。

由于默认情况下UNION对每个运算符执行单独的操作,因此不合并每列的选择性,从而使它有更好的机会进行搜索。 现在,由于UNION执行两项操作,因此它们必须使用上述串联操作来匹配其结果集。 这通常不是昂贵的操作。

还应注意,OR子句的工作方式与IN语句相同。

希望本技巧对您有所帮助。 我相信这在使用需要高并发性的系统时非常有价值。

Source: https://habr.com/ru/post/zh-CN464623/


All Articles