Left join or Select in select (SQL - 查询速度)
Left join or Select in select (SQL - Speed of query)
我有这样的东西:
SELECT CompanyId
FROM Company
WHERE CompanyId not in
(SELECT CompanyId
FROM Company
WHERE (IsPublic = 0) and CompanyId NOT IN
(SELECT ShoppingLike.WhichId
FROM Company
INNER JOIN
ShoppingLike ON Company.CompanyId = ShoppingLike.UserId
WHERE (ShoppingLike.IsWaiting = 0) AND
(ShoppingLike.ShoppingScoreTypeId = 2) AND
(ShoppingLike.UserId = 75)
)
)
它有3个select,我想知道不做3个select怎么能有,100万条记录哪个速度更快? "select in select" 或 "left join"?
我的经验来自 Oracle。优化棘手的查询永远没有正确答案,这是你和优化者之间的协作。您需要检查解释计划,有时甚至是跟踪,通常在编写查询的每个阶段,以找出优化器的想法。话虽如此:
- 您可以通过将其子查询
WHERE
子句的全部内容放入 NOT(
...)
来删除外部 SELECT
。从表面上看,它会阻止对 Company(或其 CompanyId 的索引)的外部全面扫描。尝试一下,检查输出是否相同并获取时间,然后在尝试下面的操作之前暂时将其删除。由于创建了隐式 OR,NOT()
很可能会导致优化器停止考虑针对 ShoppingLike 子查询的 ANTI-JOIN。
- 确保将 CompanyId 和 WhichId 定义为
NOT NULL
列。如果没有这个(或明确的 CompanyId IS NOT NULL
之类的东西),那么 ANTI-JOIN 选项通常会被丢弃。
- 最内部的子查询不相关(不引用其外部查询中的任何内容)因此可以单独提取和调整。就风格而言,我会交换
INNER JOIN
周围的 table 名称,因为您希望首先扫描 ShoppingLike,因为它具有针对它的所有过滤器。它不会有任何区别,但它更容易阅读,并且可以使用提示按指定的顺序扫描 tables。我什至会质疑在这个子查询中是否需要 Company table。
- 您曾经使用过
NOT IN
,而有时非常相似的 NOT EXISTS
会提供优化器 more/alternative 选项。
除非您开始尝试解释计划,否则以上所有内容都只是反复试验。 Oracle可以,顺风顺水,在LEFT JOIN
和IN
SELECT
之间转换。超过 100 万行将创造投资时间。
我有这样的东西:
SELECT CompanyId
FROM Company
WHERE CompanyId not in
(SELECT CompanyId
FROM Company
WHERE (IsPublic = 0) and CompanyId NOT IN
(SELECT ShoppingLike.WhichId
FROM Company
INNER JOIN
ShoppingLike ON Company.CompanyId = ShoppingLike.UserId
WHERE (ShoppingLike.IsWaiting = 0) AND
(ShoppingLike.ShoppingScoreTypeId = 2) AND
(ShoppingLike.UserId = 75)
)
)
它有3个select,我想知道不做3个select怎么能有,100万条记录哪个速度更快? "select in select" 或 "left join"?
我的经验来自 Oracle。优化棘手的查询永远没有正确答案,这是你和优化者之间的协作。您需要检查解释计划,有时甚至是跟踪,通常在编写查询的每个阶段,以找出优化器的想法。话虽如此:
- 您可以通过将其子查询
WHERE
子句的全部内容放入NOT(
...)
来删除外部SELECT
。从表面上看,它会阻止对 Company(或其 CompanyId 的索引)的外部全面扫描。尝试一下,检查输出是否相同并获取时间,然后在尝试下面的操作之前暂时将其删除。由于创建了隐式 OR,NOT()
很可能会导致优化器停止考虑针对 ShoppingLike 子查询的 ANTI-JOIN。 - 确保将 CompanyId 和 WhichId 定义为
NOT NULL
列。如果没有这个(或明确的CompanyId IS NOT NULL
之类的东西),那么 ANTI-JOIN 选项通常会被丢弃。 - 最内部的子查询不相关(不引用其外部查询中的任何内容)因此可以单独提取和调整。就风格而言,我会交换
INNER JOIN
周围的 table 名称,因为您希望首先扫描 ShoppingLike,因为它具有针对它的所有过滤器。它不会有任何区别,但它更容易阅读,并且可以使用提示按指定的顺序扫描 tables。我什至会质疑在这个子查询中是否需要 Company table。 - 您曾经使用过
NOT IN
,而有时非常相似的NOT EXISTS
会提供优化器 more/alternative 选项。
除非您开始尝试解释计划,否则以上所有内容都只是反复试验。 Oracle可以,顺风顺水,在LEFT JOIN
和IN
SELECT
之间转换。超过 100 万行将创造投资时间。