如何在T-SQL中优化多表排序的连接?

时间:2011-07-14 21:59:25

标签: sql sql-server sql-server-2005 tsql query-optimization

如何优化以下查询?

   SELECT TOP 50 *
     FROM A 
LEFT JOIN B ON A.b_id = B.id 
 ORDER BY A.number, B.name DESC

我在(A.number asc,A.creation_date desc)上创建了一个非聚集索引,其中包括A中的所有列,以及B.origination_date desc上的另一个非聚集索引,其中包括B中的所有列(除了文字栏)。根据SQL Server Management Studio的实际执行计划,这两个索引都没有使用。

似乎导致性能下降的是B.origination_date排序。当我在SQL Server Management Studio中检查实际执行计划时,我发现这三个字段中的“Top N Sort”占用了91%的执行时间。如果我在B.origination_date上删除排序,则查询几乎立即完成,使用A上的索引。

修改 更新了查询以提供更好,更简单的示例。

3 个答案:

答案 0 :(得分:5)

我猜是 A.number喜欢'%%'是你的问题。这是打算做什么的?如果要使用索引,则不应使用带通配符的like作为第一个字符。因为这看起来似乎是没有任何过滤,因为通配符之间没有任何东西。

答案 1 :(得分:1)

没有动手访问,很难提出硬性和快速的解决方案。一些想法和建议:

如果没有表B上的连接,则所有SQL必须执行(使用A.Number上的索引),直到找到与您的模式匹配的前50行。如果“Number”的值相对唯一(没有多少重复[这是基数]),那么在索引中使用Creation_Date也没什么价值。

为什么左外连接到B?是[零或一],还是一到[零或多]?如果基数很低(A中有很多重复),则需要连接才能清楚地找到“前50”,否则会认为连接不会影响性能,而不需要执行连接。我看不到B上的任何索引(除了列id)在这里有任何区别。嗯,你确实有B.Id的索引,对吧?如果没有,那可能会大大减慢速度(当然,假设B有很多行)。

对于更多的特殊情况,我想查看连接的基数和按列排序,并仔细查看“with join”查询的执行计划。


附加物

如果A的基数较低(许多重复),那么查询优化器可能会“认为”它必须使用很多B.Id来解决排序(必须这样才能找到前50名)。这可能解释了它为什么会这样做。

如果他们将产生100%相同的结果,我建议用INNER联接替换LEFT联接。通常,当更严格的连接条件到位时,查询计划可以变得更加简单。

答案 2 :(得分:1)

由于您要对来自两个不同表的列进行排序,因此SQL Server必须加入表,然后进行排序。表连接后,各个表上的索引对排序没有帮助。索引视图可能是您最好的选择。