2016-07-23 50 views
0

我有这样的事情:LEFT JOIN或选择选择(SQL - 查询的速度)

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个选择,我想知道我怎么能有它未做3种选择,而这一个有100万条记录更好的速度? “select in select”或“left join”?

+0

如果性能出现问题,请尝试使用硬件上数据库上数据的每个版本,并查看哪个更快。 –

+0

它有两个问题,我无法准备左连接,对于大数据我无法测试它,因为我没有:(如果MS SQL为你做了 – dan

+0

,那么不要担心,因为它的优化器会优化你可以在companyId上创建索引,以帮助MS SQL更快地完成查询。 – Mahmoud

回答

0

我的经验来自Oracle。优化棘手的查询永远不会有正确的答案,这是您与优化器之间的协作。在编写查询的每个阶段,您都需要检查解释计划和有时候的痕迹,以找出优化者的想法。话虽如此:

  • 你可以通过把它的全部内容删除外SELECT是在一个NOT( ... )子查询WHERE条款。表面上会阻止公司的外部全面扫描(或者它是CompanyId的索引)。尝试一下,检查输出是否相同并获取时间,然后在尝试下面的内容之前暂时将其删除。 NOT()很可能会导致优化程序因创建隐式OR而停止考虑针对ShoppingLike子查询的ANTI-JOIN。
  • 确保CompanyId和WhichId定义为NOT NULL列。没有这个(或者明确的CompanyId IS NOT NULL),那么ANTI-JOIN选项通常会被丢弃。
  • 最内层的子查询不相关(不引用任何来自外层查询的内容),因此可以分别提取和调整。就风格而言,我会将表名称换成INNER JOIN,因为您希望首先扫描ShoppingLike,因为它具有针对它的所有过滤器。它不会产生任何影响,但它更容易阅读,并可以使用提示以指定顺序扫描表。我甚至会质疑这个子查询中公司表的需求。
  • 您已使用NOT IN有时非常相似的NOT EXISTS为优化器提供了更多/备选选项。

除非您开始尝试解释计划,否则以上所有内容都只是试验和错误。甲骨文可以通过以下方式在LEFT JOININ之间转换SELECT。 1M +行将创造投资时间。

+0

所以谢谢:)它比我需要的更多帮助我 – dan