作为MS SQL 2000和2005的DBA,我经常看到巨大的选择查询加入7-10甚至更多的表。但是,我发现,性能往往会受到影响,并且查询变得非常难以调试和/或改进。
当我应该考虑其他查询方法时,有一个“经验法则”,比如临时表来保存初步结果吗?或者有一点,SQL查询优化器在确定最佳计划方面做得不好?
答案 0 :(得分:8)
很多时候你可以通过创建帮助视图来缓解视觉气味,我认为没有一个严格的快速规则来确定有多少连接被认为是坏的。
与过程编码不同,将SQL分解成一些小块可能会导致查询效率低下。
SQL Optimiser可以很好地处理大量的表连接,如果你遇到了一个角点,你可以使用提示指定连接顺序或样式。实际上,我认为获得加入超过10个表的查询是非常罕见的,但是在报告类型场景中这可能发生这种情况是非常可行的。
如果您发现有大量连接的情况并且发现此特定查询是瓶颈并且您已准备好所有正确的索引,则可能需要重构。但是,请记住,大量连接可能只是症状,而不是问题的根本原因。应遵循查询优化的标准做法(查看分析器,查询计划,数据库结构,逻辑等)
SQL Server无论如何都使用tempdb进行合并连接,因此通常不需要创建临时表来重构单个SELECT查询。
答案 1 :(得分:1)
这实际上取决于你的桌子有多大,即使你只有2张桌子连在一起,如果它有100M的记录,那么无论如何这将是一个缓慢的过程。
如果表a中的X记录和表b中的Y记录,如果将它们连接在一起,则可能会回到x * y记录,在这种情况下,交换内存将在此过程中使用,这比较慢,相比之下,小查询只使用具有最佳性能的CPU L2缓存。
但是,如果您觉得确实需要加入很多表来实现目标,我建议您的数据库过度规范化,第三次规范化在大多数情况下工作得非常好,不要尝试吐出信息很多,因为它被认为是低效的查询。
是的,如有必要,请创建一个表来缓存重度查询的结果,并仅在必要时更新字段,甚至每天更新一次。
答案 2 :(得分:0)
我也看到加入7-10个表的庞大查询,但从我看到的查询优化器似乎总是找到最有效的计划 - 当然我在这些复杂问题中看到的所有性能问题通常都与一些其他问题(例如条件WHERE语句或嵌套子查询)
答案 3 :(得分:0)
优化器为自己设置时间限制,以防止它运行太长时间。许多表的问题在于,每个表都会将优化程序可能的计划数量相乘(实际上它是连接数,而不是表本身)。在某些时候,优化器会耗尽时间,并且只会使用它迄今为止的最佳计划,这可能非常糟糕。
那么这一点到底是什么?嗯,这是非常情况化的,2005年比2000好很多,但我通常的经验法则是SQL Server 2000为4-8,SQL Server 2005为6-16。
答案 4 :(得分:0)
根据我的经验,还有其他变量对整体查询计划和性能产生了更为显着的影响,例如:
在查询中可能只有两个表连接在一起,但如果一个键列是GUID而另一个是GUID的varchar表示,则在任何地方都没有索引,并且每个表都有200万行,那么你的表现可能会很差。
我以前用10个以上的联接编码报告查询,并且在外键列上明智地使用一些非聚集索引通常会对计划产生最大的好处。