【问题标题】:Speeding up inner joins between a large table and a small table加快大表和小表之间的内连接
【发布时间】:2011-01-16 10:50:31
【问题描述】:

这可能是一个愚蠢的问题,但它可能会阐明连接在内部是如何工作的。

假设我有一个大表 L 和一个小表 S(100K 行与 100 行)。

下面两个选项在速度上会不会有区别?:

OPTION 1:                 OPTION 2:
---------                 ---------
SELECT *                  SELECT *
FROM L INNER JOIN S       FROM S INNER JOIN L
ON L.id = S.id;           ON L.id = S.id;

请注意,唯一的区别是表连接的顺序。

我意识到不同 SQL 语言的性能可能会有所不同。如果是这样,MySQL 与 Access 相比如何?

【问题讨论】:

    标签: sql query-optimization


    【解决方案1】:

    不,顺序无关紧要。

    几乎所有 RDBMS(如 MS Access、MySQL、SQL Server、ORACLE 等)都使用基于列统计的成本优化器。在大多数情况下,优化器会选择正确的计划。在您给出的示例中,顺序无关紧要(只要统计数据是最新的)。

    要决定使用什么查询策略, Jet Engine 优化器使用 统计数据。以下因素是 这些因素中的一些 统计数据基于:

    • 一个表的记录数
    • 表中的数据页数
    • 桌子的位置
    • 索引是否存在
    • 索引的唯一性

    注意:您无法查看 Jet 数据库引擎优化方案,并且您 无法指定如何优化 询问。但是,您可以使用 数据库记录器确定 索引是否存在以及如何 索引是唯一的。

    根据这些统计数据, 优化器然后选择最好的 交易内部查询策略 使用特定的查询。

    统计信息会在任何时候更新 查询已编译。已标记查询 保存时进行编译 对查询(或其 基础表)和当 数据库被压缩。如果查询是 标记为编译,编译 并更新统计信息 下次运行查询时。 编译通常从一个 秒到四秒。

    如果您添加大量 记录到您的数据库中,您必须 打开然后将您的查询保存到 重新编译查询。例如,如果 您设计然后通过以下方式测试查询 使用一小组样本数据,您 之后必须重新编译查询 额外的记录被添加到 数据库。当你这样做时,你想要 确保最佳查询 当你的性能达到 应用程序正在使用中。

    Ref.

    可能感兴趣:ACC: How to Optimize Queries in Microsoft Access 2.0, Microsoft Access 95, and Microsoft Access 97

    Tony Toews 的Microsoft Access Performance FAQ 值得一读。

    “加入顺序无关紧要”有一个警告。

    如果您的 RDBMS 的基于成本的查询优化器在创建查询计划时超时,那么连接顺序可能很重要。基于成本的优化器具有有限的资源(CPU 时间和内存)来构建查询计划。如果它们在编译阶段超时,您将获得迄今为止找到的最佳计划。

    TLDR;如果您有复杂的查询会收到计划编译超时(不是查询执行超时),那么首先放置您最严格的连接。这样,当查询计划优化器超时时,它会增加找到“更好”计划的机会。

    当然,如果您遇到查询计划编译超时,您可能应该简化您的查询。

    【讨论】:

    • 那么,鉴于两个表都有唯一的索引,性能会因情况而异?
    • @Zaid:如果统计数据是最新的(并且如上所述重新编译查询),那么连接的顺序将无关紧要;优化器会选择正确的方式。
    【解决方案2】:

    我知道甲骨文不在你的名单上,但我认为大多数现代数据库都会这样做。

    您可以在下面的执行计划中看到,这两个语句之间没有区别。

    这是对两个表中每一个的完全访问(在我的情况下没有索引),然后是 HASH JOIN。由于您需要两个表中的所有内容,因此需要读取和连接两个表,因此顺序没有影响。

    ---------------------------------------------------------------------------
    | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    ---------------------------------------------------------------------------
    |   0 | SELECT STATEMENT   |      |   100 |   700 |    42  (12)| 00:00:01 |
    |*  1 |  HASH JOIN         |      |   100 |   700 |    42  (12)| 00:00:01 |
    |   2 |   TABLE ACCESS FULL| S    |   100 |   300 |     2   (0)| 00:00:01 |
    |   3 |   TABLE ACCESS FULL| L    |   100K|   390K|    38   (8)| 00:00:01 |
    ---------------------------------------------------------------------------
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-10
      • 2010-09-15
      • 2012-04-25
      • 1970-01-01
      • 1970-01-01
      • 2021-11-15
      相关资源
      最近更新 更多