【问题标题】:SQL Server 2005 - Join does not terminate - Speed issue?SQL Server 2005 - 加入不会终止 - 速度问题?
【发布时间】:2010-12-13 07:20:55
【问题描述】:

有没有人知道为什么这个连接操作没有终止:

SELECT * FROM
(SELECT LOWER([Computer Name]) AS 'cname' FROM table1)
AS export,
(SELECT AssetID AS 'CCID', Hostname AS 'cname' FROM table2 WHERE LastVersionFlag=1)
AS known

WHERE export.cname = LEFT(known.cname, LEN(export.cname));

我要解决的问题是:

  • Table1 列“cname”包含:“pc1”
  • Table2 列“主机名”包含:“pc1.domain.com”
  • 表 2 还包含列“CCID”:123123

作为查询的结果,我需要从 table1 接收每个“cname”的 CCID。

编辑:

查询现在运行超过 15 分钟,并且没有产生任何输出,也没有终止。

  • Table1 包含大约 100.000 行
  • Table2 包含大约 200.000 行

任何想法如何加快查询?!

编辑2:

索引放在Table1 cname和Table2 cname上

任务计划如下所示:http://i55.tinypic.com/1z3o0t4.png

【问题讨论】:

    标签: sql-server-2005 join


    【解决方案1】:

    这是您要找的基本连接吗?

    SELECT known.CCID, export.[Computer Name] AS cname 
    FROM
    table1 AS export
    INNER JOIN table2 AS known ON LOWER(export.[Computer Name]) = LOWER(LEFT(known.cname, LEN(export.[Computer Name])))
    WHERE LastVersionFlag=1 
    

    编辑: 以下是加快查询速度的一些建议:

    首先,join 中的字符串操作开销很大。如果您对连接强制使用不区分大小写的排序规则,则可以避免调用 lower()。

    例如...ON known.cname = export.[Computed Column] collate SQL_Latin1_General_Cp437_CI_AS_KI_WI

    您最好的做法是在 table2 上创建一个持久计算列,该列使用来自连接 LEFT(known.cname, LEN(export.[Computer Name])) 的公式仅包含 cname,然后您可以在计算列以及 table1 的 cname 列上放置索引。一旦完成,您的连接将是一个简单的相等,而不是一个严重操纵的比较。这将允许查询引擎制定更优化的计划。

    【讨论】:

    • 没错。据我所知,您的查询执行与我相同的操作并且也不会终止...
    • 请问您所说的“不终止”是什么意思?
    【解决方案2】:

    附注:默认情况下,SQL Server 在不区分大小写模式下工作(如果您没有进行任何更改),因此您通常不必关心大写/小写。 使用LOWER 之类的函数会阻止索引的使用。

    为了加快最后一个WHERE,您可以使用LIKE 重写它,这将利用相关列上的索引(如果有的话)。这将类似于(如 devio 的回答):

    known.cname LIKE (export.cname + '%')
    

    【讨论】:

      【解决方案3】:

      将所有建议汇总在一起会为您提供以下查询。
      通过正确的索引和您提到的记录数,返回结果应该不会花费几分钟。

      SELECT  cname = t1.[Computer Name] 
              , CCID = k.AssetID
              , Hostname = k.cname
      FROM    table1 t1
              INNER JOIN known k ON k.Hostname LIKE t1.[Computer Name]  + '%'
      WHERE   k.LastVersionFlag = 1        
      

      【讨论】:

      • 感谢您的输入,我相应地调整了我的查询。然而,它需要大约 20 分钟的时间来处理并返回一个空的结果集。我对此没有任何解释,因为这两个表中有匹配项......
      • @Michael,你能给我们看看 SHOWPLAN 语句的输出吗?
      • 展示计划与我在主题中作为编辑发布的计划不同吗?
      【解决方案4】:

      我的猜测是由于数据的大小,您的查询没有执行。

      需要生成100.000 * 200.000行的Cartesian product,然后应用WHERE条件。

      如果列的排序规则设置为不区分大小写(数据库和服务器排序规则默认设置),则 SQL Server 比较不区分大小写。

      要加快连接操作,请在 table1.[Computer Name] 和 table2.Hostname 上添加(唯一?)索引。

      将您的查询修改为

      SELECT known.CCID, export.[Computer Name] AS cname 
      FROM table1 AS export
      INNER JOIN table2 AS known 
          ON known.Hostname LIKE export.[Computer Name] + '%' 
          AND LastVersionFlag=1 
      

      如果您的所有主机名都使用点分 cname 表示法,请使用 '.%'。

      【讨论】:

      • 感谢您的输入,我相应地调整了我的查询。然而,它需要大约 20 分钟的处理时间并返回一个空的结果集。我对此没有任何解释,因为这两个表中有匹配项......
      猜你喜欢
      • 2013-01-01
      • 2011-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多