SQL Server 2000“NO JOIN PREDICATE”警告 - 为什么?

时间:2008-11-14 17:59:43

标签: sql sql-server tsql warnings

我对SQL Server 2000有一个奇怪的问题,我想不出这个问题发生的原因。

有两个表,两个表都有一个组合主键和聚簇索引,两个键具有相同的结构:

(VARCHAR(11), INT, DATETIME)   /* can't change this, so don't suggest I should */

所以,像这样加入他们很容易:

SELECT t1.Foo, t2.Bar
FROM   table1 t1 INNER JOIN table2 t2 ON t1.VarcharKey = t2.VarcharKey
WHERE  t1.VarcharKey = 'Foo'

查看查询执行计划,我看到了:

  • Clustered Index Seek [db]。[dbo]。[table1]。[PK_table1](48%)
  • Clustered Index Seek [db]。[dbo]。[table2]。[PK_table2](51%)
  • 嵌套循环(内部联接)(1%)警告:没有加入预测
  • 选择(0%)

现在如果我这样做(注意NVARCHAR字符串!):

SELECT t1.Foo, t2.Bar
FROM   table1 t1 INNER JOIN table2 t2 ON t1.VarcharKey = t2.VarcharKey
WHERE  t1.VarcharKey = N'Foo'

我明白了:

  • 聚集索引扫描[db]。[dbo]。[table1]。[PK_table1](98%)
  • Clustered Index Seek [db]。[dbo]。[table2]。[PK_table2](1%)
  • 嵌套循环(内部联接)(1%)此处没有警告
  • 选择(0%)

这种行为让我有些困惑。

  • 为什么会出现“NO JOIN PREDICATE”警告,当我将'Foo'更改为N'Foo'时,为什么会消失?我的关键列不是NVARCHAR类型,所以这应该没有任何区别,或应该是吗?
  • 此警告的存在是否会产生负面影响,还是可以忽略它?
  • 为什么要从索引搜索切换到索引扫描?

一些背景信息:表基数为ca. 25,000条记录一张桌子,约另一个有12,000条记录。数据库兼容级别为80(SQL Server 2000)默认排序规则为SQL_Latin1_General_CP1_CI_AS,如果这样做有任何区别。

以下是@@VERSION的内容:

  

Microsoft SQL Server 2000 - 8.00.2273(Intel X86)2008年3月7日22:19:58版权所有(c)1988-2003 Windows NT 5.0上的Microsoft Corporation Enterprise Edition(Build 2195:Service Pack 4)

P.S。:我知道KB322854,但显然不是这样。

2 个答案:

答案 0 :(得分:2)

  

为什么要从Index Seek切换   到索引扫描?

这在很大程度上是一种猜测,但这里有:

在第一种情况下('Foo'),MSSQL认识到正在搜索的值是t1上索引的第一部分的完美匹配,因此使用索引在t1中查找记录(Index Seek,可能是二分搜索)。在t1中找到了一个与t2完全匹配的索引的记录,它可以使用索引在t2中查找记录。

在第二种情况下,(N'Foo'),MSSQL认识到它在索引和被搜索的值之间没有完美的匹配,所以它不能将索引用作索引,但必须做一个完整的表扫描。但是,由于索引保存所需的信息(以不同的形式)并且小于完整表,因此它可以对索引进行全面扫描,就像它是表一样(这比扫描表更快,因为页面更少需要为磁盘读取;但是,它似乎比索引寻找的时间长约90倍)

答案 1 :(得分:0)

From SqlServerCentral

查询可以具有看似完美形成的连接条件。但是当您检查查询计划时,您将看到一个警告,指示“No Join Predicate”表示所涉及的两个表没有谓词(加入时)。向查询添加选项(强制顺序)会产生完全不同的计划,警告会消失(在某些情况下)。这就是你怎么知道这就是问题所在。我见过的大多数在SQL 2000上表现更好的查询都表现出这个问题。 SP 2的累积更新4应该可以解决问题。