17

我想从一个字段中找到最高的 AutoIncremented 值。(在我可以使用的插入之后,它没有被获取@@SCOPE_IDENTITY等)这两个查询中的哪一个会运行得更快或提供更好的性能。 Id是 的主键和autoincrement字段Table1。这是针对 Sql Server 2005 的。

SELECT MAX(Id) FROM Table1

SELECT TOP 1 Id FROM Table1 ORDER BY Id DESC

[编辑]
是的,在这种情况下Id是我定义聚集索引的字段。
如果索引是ID DESC什么..是的,如果 1.Id 是聚集索引 + 主键
,那么很高兴知道性能会受到怎样的影响。 2.id是聚集索引,不是主键。 3.id是非聚集索引ASC+主键。 4.id是非聚集索引ASC,不是主键。 5.id是非聚集索引DESC+主键。 6. id是非聚集索引DESC而不是主键。 7. 身份证只是






AutoIncrement

希望这不是一个艰巨的任务!

4

7 回答 7

10

没有人提到 IDENT_CURRENT('Table1') - 把他们都吹走了 - 当然它只适用于身份列,但这就是问题......

于 2009-08-12T15:41:39.650 回答
9

如果有聚集索引,则两个查询之间的性能几乎没有差异。

这是因为两者都将执行将承担 100% 查询成本的聚集索引扫描。

对没有索引的列执行两个查询会导致在两个执行计划中使用 3 个运算符。

Top 子句使用 Sort 运算符,Max 函数使用 Stream Aggregate 运算符。

当没有索引时,MAX() 函数提供更好的性能。

可以在此处找到概念证明,并且可以在此处找到测试场景的完整演练:

性能比较 Top 1 Verses MAX() 函数

于 2009-02-26T11:59:57.500 回答
8

理论上,他们将使用相同的计划并几乎同时运行。

在实践中,

SELECT TOP 1 Id FROM Table1 ORDER BY Id DESC

更有可能使用PRIMARY KEY INDEX.

此外,如果您决定选择其他列以及id.

一个实际的计划MAX()说:

SELECT <- AGGREGATE <- TOP <- CLUSTERED INDEX SCAN

,而计划TOP 1说:

SELECT <- TOP <- CLUSTERED INDEX SCAN

,即aggregate省略。

聚合实际上不会在这里做任何事情,因为只有一行。

PS如前所述@Mehrdad Afshari@John Sansom在非索引字段MAX上稍快(当然不是20优化器所说的时间):

-- 18,874,368 行

设置语言英语
设置统计时间
设置统计 IO 开启
打印“最大”
从主服务器中选择 MAX(id)
打印“前 1 名”
SELECT TOP 1 id FROM master ORDER BY id DESC
打印“最大”
从主服务器中选择 MAX(id)
打印“前 1 名”
SELECT TOP 1 id FROM master ORDER BY id DESC
打印“最大”
从主服务器中选择 MAX(id)
打印“前 1 名”
SELECT TOP 1 id FROM master ORDER BY id DESC
打印“最大”
从主服务器中选择 MAX(id)
打印“前 1 名”
SELECT TOP 1 id FROM master ORDER BY id DESC
打印“最大”
从主服务器中选择 MAX(id)
打印“前 1 名”
SELECT TOP 1 id FROM master ORDER BY id DESC

将语言设置更改为 us_english。

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,经过时间 = 1 毫秒。

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,经过时间 = 1 毫秒。

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,经过时间 = 1 毫秒。
最大限度

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,经过的时间 = 20 毫秒。

(строкобработано: 1)
表'主'。扫描计数 3,逻辑读取 32655,物理读取 0,预读读取 447,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

SQL Server 执行时间:
   CPU 时间 = 5452 毫秒,经过时间 = 2766 毫秒。
前1名

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,经过时间 = 1 毫秒。

(строкобработано: 1)
表'主'。扫描计数 3,逻辑读取 32655,物理读取 0,预读读取 2,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

SQL Server 执行时间:
   CPU 时间 = 6813 毫秒,经过时间 = 3449 毫秒。
最大限度

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,经过时间 = 1 毫秒。

(строкобработано: 1)
表'主'。扫描计数 3,逻辑读取 32655,物理读取 0,预读读取 44,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

SQL Server 执行时间:
   CPU 时间 = 5359 毫秒,经过时间 = 2714 毫秒。
前1名

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,经过时间 = 1 毫秒。

(строкобработано: 1)
表'主'。扫描计数 3,逻辑读取 32655,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

SQL Server 执行时间:
   CPU 时间 = 6766 毫秒,经过时间 = 3379 毫秒。
最大限度

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,经过时间 = 1 毫秒。

(строкобработано: 1)
表'主'。扫描计数 3,逻辑读取 32655,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

SQL Server 执行时间:
   CPU 时间 = 5406 毫秒,经过时间 = 2726 毫秒。
前1名

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,经过时间 = 1 毫秒。

(строкобработано: 1)
表'主'。扫描计数 3,逻辑读取 32655,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

SQL Server 执行时间:
   CPU 时间 = 6780 毫秒,经过时间 = 3415 毫秒。
最大限度

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,经过时间 = 1 毫秒。

(строкобработано: 1)
表'主'。扫描计数 3,逻辑读取 32655,物理读取 0,预读读取 85,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

SQL Server 执行时间:
   CPU 时间 = 5392 毫秒,经过时间 = 2709 毫秒。
前1名

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,经过时间 = 1 毫秒。

(строкобработано: 1)
表'主'。扫描计数 3,逻辑读取 32655,物理读取 0,预读读取 10,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

SQL Server 执行时间:
   CPU 时间 = 6766 毫秒,经过时间 = 3387 毫秒。
最大限度

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,经过时间 = 1 毫秒。

(строкобработано: 1)
表'主'。扫描计数 3,逻辑读取 32655,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

SQL Server 执行时间:
   CPU 时间 = 5374 毫秒,经过时间 = 2708 毫秒。
前1名

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,经过时间 = 1 毫秒。

(строкобработано: 1)
表'主'。扫描计数 3,逻辑读取 32655,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

SQL Server 执行时间:
   CPU 时间 = 6797 毫秒,经过时间 = 3494 毫秒。
于 2009-02-26T11:11:31.517 回答
3

只需比较执行计划,您就会看到(Ctrl+M编辑查询时在 Management Studio 中按下)。我的疯狂猜测是,只要Id列上有(聚集)索引,这些查询的性能相同。

然而,这作为一个整体是一个非常糟糕的主意。

于 2009-02-26T11:12:48.050 回答
2

MAX一般比较快。

如果存在,两个查询都将使用列上的索引。

如果列上不存在索引,则TOP 1查询将使用Top N Sort运算符对表进行排序,而不是流聚合,这会使其变慢。

MAX还提供了更好的可读性。

旁注:虽然MAX将在索引情况下的执行计划中使用流聚合运算符,但它没有任何特定成本,因为它只是处理单行(Actual Rows = 1)。您可以通过在单个批次中运行查询来比较查询并查看相对成本。在索引的情况下,两个查询都将花费 50%。我在一个大约有 7000 行的表上测试了非索引案例,与成本为 35% 的 MAX 相比,TOP 的成本为 65%。

于 2009-02-26T11:17:12.970 回答
2

我刚刚针对典型数据集测试了您提供的两个 SQL 语句:

SELECT MAX(Id) FROM Table1

SELECT TOP 1 Id FROM Table1 ORDER BY Id DESC

并且SELECT TOP 1 Id FROM Table1 ORDER BY Id DESC稍微快一点,因为它在执行计划中少了一个步骤。以下是每个查询执行的执行计划:

从表 1 中选择 MAX(Id)

聚集索引扫描 >> 顶部 >> 流聚合 >> 选择

SELECT TOP 1 Id from Table1 ORDER BY Id DESC

聚集索引扫描 >> 顶部 >> 选择

于 2009-02-26T12:06:58.513 回答
1

是的,在这种情况下,Id 是我定义聚集索引的字段。如果索引是 ID DESC 那么什么.. 是的,很高兴知道如果

  1. Id 是聚集索引 + 主键。
  2. Id 是聚集索引而不是主键。
  3. Id 是非聚集索引 ASC + 主键。
  4. Id 是非聚集索引 ASC,而不是主键。
  5. Id 是非聚集索引 DESC + 主键。
  6. Id 是非聚集索引 DESC 而非主键。
  7. Id 只是自动增量

对于案例 1 和 2,两者都将执行返回单个记录的聚集索引扫描。两个查询之间没有 IO 差异。

对于案例 3、4、5 和 6,两者都将执行返回单个记录的索引扫描。两个查询之间没有 IO 差异。

对于案例 7,两者都将执行表扫描。IO成本没有区别。

总结:案例1-6都是赢了!如果您处于案例 7 中,那么从 IO 的角度来看,您已经失败了。

您可以使用 SQL 的查询分析器来测量 IO。在查询之前运行它。

SET STATISTICS IO ON
于 2009-02-26T19:27:02.480 回答