【问题标题】:How many tables is "too many" in a single SQL SELECT?单个 SQL SELECT 中有多少表是“太多”?
【发布时间】:2009-06-09 22:50:25
【问题描述】:

作为 MS SQL 2000 和 2005 的 DBA,我经常看到巨大的选择查询加入 7-10 个甚至更多的表。不过,我发现,在某个时间点过后,性能往往会受到影响,并且查询变得非常难以调试和/或改进。

那么当我应该考虑其他查询方法(例如保存初步结果的临时表)时,是否有“经验法则”?还是在某个点之后 SQL 查询优化器无法很好地找出最佳计划?

【问题讨论】:

标签: sql-server tsql


【解决方案1】:

很多时候你可以通过创建辅助视图来减轻视觉上的异味,我不认为有多少连接被认为是坏的。

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

SQL 优化器可以很好地处理大量的表连接,如果遇到特殊情况,您可以使用提示指定连接顺序或样式。实际上,我认为很少有查询连接超过 10 个表,但在报告类型的场景中发生这种情况是非常可行的。

如果您发现存在大量连接的情况,并且发现此特定查询是一个瓶颈,并且您拥有所有正确的索引,则可能需要重构。但是,请记住,大量连接可能只是症状,而不是问题的根本原因。应遵循查询优化的标准做法(查看分析器、查询计划、数据库结构、逻辑等)

SQL Server 无论如何都使用 tempdb 进行合并连接,因此通常不需要创建临时表来重构单个 SELECT 查询。

【讨论】:

  • 我回避辅助视图,因为它们经常包含额外的列、过滤器、逻辑或连接,这可能会使视图在一般意义上“很好”使用,但可能不是特定查询所必需的。我刚刚重构了一个复杂的查询,该查询在未索引的列上使用了一个特别糟糕的视图和一个无用的过滤器。 (“WHERE INACTIVE = 0”,但 1600 万行实际上没有设置此标志)
  • 没错,就像任何一点重构一样,这种技术都可能被滥用。我认为你应该考虑帮助视图,如果它可以帮助多个查询(不仅仅是重构单个查询)
【解决方案2】:

这真的取决于你的表有多大,即使你只将 2 个表连接在一起,如果它有 1 亿条记录,那么无论如何这将是一个缓慢的过程。

如果你在表 a 中有 X 条记录,在表 b 中有 Y 条记录,如果你将它们连接在一起,你可能会得到最多 x*y 条记录,在这种情况下,交换内存将在此过程中使用,那会很慢,比较一下,小查询只使用性能最好的CPU L2缓存。

但是,如果你觉得真的需要加入很多表来实现目标,我建议你的数据库过度规范化,第三规范化在大多数情况下工作得很好,不要试图吐出信息much ,因为它认为查询效率低下。

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      优化器为自己设置了一个时间限制,以防止它运行太久。许多表的问题在于,每个表都会增加优化器评估的可能计划的数量(实际上是连接的数量,而不是表本身)。在某些时候,优化器会用完时间,只会使用迄今为止最好的计划,这可能会很糟糕。

      那么这一点在哪里?嗯,这是非常有情境的,2005 比 2000 好得多,但我通常的经验法则是 SQL Server 2000 为 4-8,SQL Server 2005 为 6-16。

      【讨论】:

        【解决方案5】:

        根据我的经验,还涉及对整体查询计划和性能有更显着影响的其他变量,例如:

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

        您可能只有两个表在查询中连接在一起,但如果一个键列是 GUID,另一个是 GUID 的 varchar 表示,则您在任何地方都没有索引,并且每个表有 200 万行,那么你的性能可能会很差。

        我之前编写了包含 10 多个连接的报告查询,并且在外键列上明智地使用一些非聚集索引通常对计划有最大的好处。

        【讨论】:

        • 如果您有很多连接,SQL Server 优化器不会查看您的所有连接,因此如果您知道某些连接在您的查询中比其他连接更有帮助,那么将它们向上移动是有好处的在列表中。
        猜你喜欢
        • 2010-09-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-31
        • 2012-01-28
        • 2021-03-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多