代码之家  ›  专栏  ›  技术社区  ›  BradC

一个SQL select中有多少表“太多”?

  •  9
  • BradC  · 技术社区  · 15 年前

    作为MS SQL 2000和2005的DBA,我经常看到巨大的选择查询加入7-10甚至更多的表。不过,我发现有一点过去了,性能往往会受到影响,查询变得很难调试和/或改进。

    那么,当我应该考虑其他查询方法(比如临时表)来保存初步结果时,是否有一个“经验法则”?或者,在某个时刻之后,SQL查询优化器就不能很好地确定最佳计划了吗?

    5 回复  |  直到 15 年前
        1
  •  8
  •   Sam Saffron James Allen    15 年前

    很多时候你可以通过创建助手视图来减轻视觉气味,我不认为有一个硬性和快速的规则可以确定有多少连接被认为是坏的。

    与过程性编码不同,将SQL分解为小块会导致查询效率低下。

    SQL乐观器可以很好地处理大量的表联接,如果遇到了一个小问题,可以使用提示指定联接顺序或样式。实际上,我认为很少有查询连接超过10个表,但在报告类型的场景中,这是非常可行的。

    如果您发现一种情况,即您有大量的连接,并且发现这个特定的查询是一个瓶颈,并且您有所有正确的索引,那么您可能需要重构。但是,请记住,大量联接可能只是 症状 而不是 根本原因 关于这个问题。应遵循查询优化的标准实践(查看探查器、查询计划、数据库结构、逻辑等)。

    SQL Server仍然将tempdb用于合并联接,因此通常不需要创建temp表来重构单个select查询。

        2
  •  1
  •   Shuoling Liu    15 年前

    这真的取决于你的桌子有多大,即使你只把两张桌子连在一起,如果它有100米的记录,那么这将是一个缓慢的过程。

    如果在表A中有X条记录,在表B中有Y条记录,如果将它们连接在一起,可能会返回最多X*Y条记录,在这种情况下,交换内存将在进程中使用,这将很慢,相比之下,小查询jonly使用的是性能最好的CPU L2缓存。

    但是,如果您觉得真的需要加入许多表来实现目标,我建议您的数据库过度规范化,第三个规范化在大多数情况下都非常有效,不要试图吐痰太多信息,因为它被认为是查询效率低下。

    是的,如果需要,请创建一个表来缓存重查询的结果,并且仅在需要时更新字段,甚至每天只更新一次。

        3
  •  0
  •   Justin    15 年前

    我也看到庞大的查询加入了7-10个表,但从我所看到的,查询优化者似乎总能找到最有效的计划——当然,我在这些复杂问题中看到的所有性能问题通常都与其他一些问题有关(如条件WHERE语句或嵌套子查询)。

        4
  •  0
  •   RBarryYoung    15 年前

    优化器为自己设置了一个时间限制,以防止它运行得太长。许多表的问题在于,每个表都乘以优化器要评估的可能计划的数量(实际上是联接的数量,而不是表本身)。在某种程度上,优化器会耗尽时间,只会使用到目前为止最好的计划,这可能非常糟糕。

    那么这一点在哪里呢?嗯,这是非常情景化的,2005年要比2000年好得多,但我通常的经验法则是4-8(对于SQL Server 2000)和6-16(对于SQL Server 2005)。

        5
  •  0
  •   Sam    15 年前

    根据我的经验,还有其他一些变量对整个查询计划和性能有更重要的影响,例如:

    • 每个联接运算符的输入行计数
    • 首先如何有效地检索输入数据
    • 要联接的列的大小和类型(例如类型转换、可空性)

    在一个查询中,可能只有两个表被联接在一起,但是如果一个键列是guid,另一个是guid的varchar表示,那么您在任何地方都没有索引,并且每个表都有200万行,那么您可能会得到非常差的性能。

    我以前用10个以上的连接对报告查询进行过编码,在外键列上明智地使用一些非聚集索引通常对计划有最大的好处。