【问题标题】:Does the order of tables in straight joins, with no hint directives, affect performance?没有提示指令的直接连接中的表顺序是否会影响性能?
【发布时间】:2012-07-10 06:13:24
【问题描述】:

所有基于 SQL 的 RDBMS(版本长达 10 年):

直接连接查询(没有提示指令)中的表顺序是否会影响最佳性能和内存管理?听说最后一个join应该是最大的表。您的数据库的查询优化器如何处理这种情况?

【问题讨论】:

  • 是的,尤其是在 MySql 上。虽然在某些数据库上没关系,但我曾经将一个使用 MySql 的应用程序移植到 Postgresql,MySql 中的慢查询在 Postgresql 中变得更快。在 MySql 上,我必须做不同的加入顺序以使查询更快
  • @Yaroslav 我的问题与外部联接无关,而是与完全联接有关。
  • 我的评论是轶事,但我忘了写博客。所以我只是在谷歌上搜索了一些类似的案例,这是我发现的:forums.mysql.com/read.php?24,79125,79434#msg-79434 如果您的 RDBMS 在确定连接的最佳顺序(带有较少中间行的连接)方面不是很聪明,您必须覆盖连接顺序你自己,例如dba-oracle.com/art_dbazine_oracle10g_dynamic_sampling_hint.htm 在 MySQL 中,为了遵守你加入表的顺序,你应该使用 STRAIGHT_JOIN;在 Oracle 中,你应该使用这个指令:/*+ ORDERED */
  • 尽管问题被标记为“Informix”,但该线程中的大多数答案——甚至是“勾选”的答案——都特定于其他数据库技术。很奇怪。

标签: mysql sql sql-server oracle informix


【解决方案1】:

回答您的问题 - 是的,表的顺序在连接中有所不同。

你也可以让优化器知道执行计划。

ORDERED 提示使 Oracle 按照它们在 FROM 子句中出现的顺序连接表。

例如,此语句将表 TAB1 连接到表 TAB2,然后将结果连接到表 TAB3:

 SELECT /*+ ORDERED */ TAB1.COL1, TAB2.COL2, TAB3.COL3
     FROM TAB1, TAB2, TAB3
    WHERE TAB1.COL1 = TAB2.COL1
         AND TAB2.COL1 = TAB3.COL1;

如果您在执行连接的 SQL 语句中省略 ORDERED 提示,优化器会选择连接表的顺序。如果您知道优化器不知道的从每个表中选择的行数,您可能希望使用 ORDERED 提示来指定连接顺序。此类信息将允许您比优化器更好地选择内部表和外部表。

通常,如果您分析表,优化器会选择一个有效的星型计划。您还可以使用提示来改进计划。最精确的方法是按照索引中键的顺序对 FROM 子句中的表进行排序,大表在后。然后使用以下提示:

/*+ ORDERED USE_NL(FACTS) INDEX(FACTS FACT_CONCAT) */

【讨论】:

    【解决方案2】:

    只是在这个主题上添加更多内容......是和否,取决于。这就是我的回答。这取决于许多因素,您使用的 RDBMS(MySQL、MSSQL Server、Oracle、DB2...)、连接类型、表大小(也就是行数)、索引等等。

    前面的答案说是和否,并呼吁在查询中使用提示。但你的问题是:

    连接语句中表的顺序是否有所不同...

    在我看来,这省略了查询提示的使用,因为您强制查询优化器使用您喜欢的顺序。

    因此,重用posted on my first comment 对您的问题的回答,@Mark Brackett 正确指出重新排列您的连接(没有查询提示)不会影响性能,因为查询优化器仍将使用目前最有效的执行计划询问。也许这不是最有效的,因此您可以使用提示并强制在连接上使用您想要的顺序,从而修改查询的执行计划。

    有关该主题的更多讨论,请访问以下链接: Does order matter in a JOIN clause? Optimize join methods

    【讨论】:

    • RE "正确地指出,重新排列连接(没有查询提示)不会影响查询优化器的性能" 根据我对 MySQL 的第一手经验,重新排列即使没有提示,连接顺序也可以使查询更快(当时我不知道查询提示)
    • 基于 Gian Maria 对weblogs.sqlteam.com/joew/archive/2008/02/29/60542.aspx 的评论之一,通过反转 Sql Server 2000 上 2 个连接的顺序,这使她的查询速度更快(尽管在 2005 年和 2008 年没关系)。猜猜这取决于 RDBMS 的智能和您使用的版本。如果您使用的 RDBMS(和版本)足够复杂,可以选择查询执行的最佳顺序,而不管表连接顺序如何,那就太好了,您可以更多地关注您的应用逻辑
    • True true :-) 我刚刚注意到 Mark Brackett 的观察“重新排列您的连接 (没有查询提示) 确实 不影响 性能”,我的一些经验表明并非如此,我只是强调 它确实有效果 即使 没有 查询提示(我的 MySql 经验),我只是重申我的经验和其他人(那些在 2000 年左右使用 Sql Server 的人)
    • @FrankComputer 一个新的东西让我学习 RE:基于成本与基于上下文(现在我才看到短语 context-based,稍后会在谷歌上搜索) .是的,这实际上取决于您的 RDBMS 将选择的查询计划;尽管如果 RDBMS 的查询计划器有点原始,它就无法为您选择最佳查询计划,它只会按照您的指示去做,因此您不会自动获得最佳性能,需要您手动干预(例如重新排列连接的表格)
    • 嗯...对我来说也是如此,RDBMS 中的“基于上下文的优化”对我来说是新的。我从语义网了解它并按上下文搜索,但与 MSSQL Server、MySQL 或 Oracle 上的查询优化器无关。可以找到很多关于查询执行计划、如何选择、重用等。例如,在 MSSQL Server 上:msdn.microsoft.com/en-us/library/ms181055(v=sql.105)
    【解决方案3】:

    没有。

    就 Informix 而言,无论如何。优化器将自行决定处理表的顺序,它们出现在FROM 子句中的顺序无关紧要。 除非您选择覆盖默认行为。

    您可以使用查询优化器的+ORDERED 提示强制它按照它们在WHERE 子句中出现的顺序加入表,即:

    SELECT --+ORDERED 
           x.col1, y.col2, z.col3
      FROM z, y, x
      WHERE ...
    

    强制优化器扫描 z、连接到 y 并连接到 x,即使这会创建一个中间笛卡尔积。所以应该小心使用它。


    注意:这个答案是在问题仅被标记为 Informix 而不是多个 RDBMS 技术时编写的。

    【讨论】:

    • 连接列上的索引或缺少索引是否会影响表的顺序?
    • 一般来说,这是准确的。在处理 Frank 的问题时,您需要注意,他有时会询问 DOS 上的 SE 4.10,大约从 1989 年开始。您所说的并非如此。
    • @FrankComputer:是的,索引的存在与否会改变查询的执行方式。这适用于启发式和基于成本的优化器(SE 4.10 使用启发式优化器;其他(更新的)版本的 Informix 数据库使用基于成本的优化器)。
    • @JonathanLeffler:是的,SE 4.10 DOS,还有:SE 7.2 UNIX 和 11.70.TC4DE (WinVista)。我很确定 4.10 是基于成本的,文档这么说加上 EXPLAIN 会相应地采取行动,尽管 SE 2.10 绝对是启发式的!无论如何,只是想知道构造连接是否是一个好习惯: 'smalltable.fk_id = bigtable.pk_id' 或 'bigtable.indexedcolumn = smalltable.nonindexedcolumn' ?
    • @FrankComputer:当您想要一个涵盖大洪水时代和大洪水后版本的软件的答案时(在任何论坛,例如 SO),您应该确定您感兴趣的版本。否则,人们会(合理地)假设您对近乎最新的版本(比如那些支持不到 5 年的版本)感兴趣,而不是旧版本。我了解你的背景,理解你的观点;不是每个人都遇到过你有些不寻常的情况。我知道没有其他人使用 5.x 版之前的 Informix 软件(但我不认识所有人)。
    猜你喜欢
    • 2019-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多