0

我在使用 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'

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

  • 聚集索引搜索 [db].[dbo].[table1].[PK_table1] (48%)
  • 聚集索引搜索 [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%)
  • 聚集索引搜索 [db].[dbo].[table2].[PK_table2] (1%)
  • 嵌套循环(内部连接)(1%)这里没有警告
  • 选择 (0%)

这种行为让我有点困惑。

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

一些背景信息:表基数约为。一张表有 25,000 条记录,大约 12,000 条记录在另一个。数据库兼容级别是 80 (SQL Server 2000),默认排序规则是SQL_Latin1_General_CP1_CI_AS,如果这有什么不同的话。

以下是 的内容@@VERSION

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

PS:我知道KB322854,但这显然不是。

4

2 回答 2

2

为什么它会从 Index Seek 切换到 Index Scan?

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

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

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

于 2008-11-14T18:31:13.373 回答
0

从 SqlServerCentral

查询可以具有看起来完美的连接条件。但是,当您检查查询计划时,您将看到一条警告,指示“无连接谓词”,表明其中 2 个涉及的表没有谓词(连接时)。向查询添加选项(强制顺序)会产生完全不同的计划,并且警告会消失(在某些情况下)。这样你就知道这是问题所在。我看到的大多数在 SQL 2000 上执行得更好的查询都表现出这个问题。SP 2 的累积更新 4 应该可以解决这个问题。

于 2008-11-14T18:18:14.630 回答