对于自动增量字段:MAX(ID)vs TOP 1 ID ORDER BY ID DESC

时间:2009-02-26 11:06:00

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

我想从字段中找到最高的AutoIncremented值。 (在我可以使用@@SCOPE_IDENTITY等插入后,它不被取出) 这两个查询中的哪一个会运行得更快或性能更好。 Idautoincrement的主键和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. Id只是AutoIncrement

希望它不是一个很高的命令!

7 个答案:

答案 0 :(得分:9)

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

这是因为它们都会执行聚集索引扫描,它将承担100%的查询费用。

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

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

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

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

Performance Comparison Top 1 Verses MAX() Funciton

答案 1 :(得分:9)

没人提到IDENT_CURRENT('Table1') - 将它们全部吹走 - 当然它只适用于标识列,但问题......

答案 2 :(得分:7)

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

在实践中,

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被省略。

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

P上。 S。注意到@Mehrdad Afshari@John Sansom,在非索引字段MAX上稍快一些(当然不是优化程序所说的20次):< / p>

-- 18,874,368 rows

SET LANGUAGE ENGLISH
SET STATISTICS TIME ON
SET STATISTICS IO ON
PRINT 'MAX'
SELECT MAX(id) FROM master
PRINT 'TOP 1'
SELECT TOP 1 id FROM master ORDER BY id DESC
PRINT 'MAX'
SELECT MAX(id) FROM master
PRINT 'TOP 1'
SELECT TOP 1 id FROM master ORDER BY id DESC
PRINT 'MAX'
SELECT MAX(id) FROM master
PRINT 'TOP 1'
SELECT TOP 1 id FROM master ORDER BY id DESC
PRINT 'MAX'
SELECT MAX(id) FROM master
PRINT 'TOP 1'
SELECT TOP 1 id FROM master ORDER BY id DESC
PRINT 'MAX'
SELECT MAX(id) FROM master
PRINT 'TOP 1'
SELECT TOP 1 id FROM master ORDER BY id DESC

Changed language setting to us_english.

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.
MAX

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 20 ms.

(строк обработано: 1)
Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 447, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
   CPU time = 5452 ms,  elapsed time = 2766 ms.
TOP 1

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

(строк обработано: 1)
Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 2, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
   CPU time = 6813 ms,  elapsed time = 3449 ms.
MAX

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

(строк обработано: 1)
Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 44, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
   CPU time = 5359 ms,  elapsed time = 2714 ms.
TOP 1

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

(строк обработано: 1)
Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
   CPU time = 6766 ms,  elapsed time = 3379 ms.
MAX

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

(строк обработано: 1)
Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
   CPU time = 5406 ms,  elapsed time = 2726 ms.
TOP 1

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

(строк обработано: 1)
Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
   CPU time = 6780 ms,  elapsed time = 3415 ms.
MAX

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

(строк обработано: 1)
Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 85, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
   CPU time = 5392 ms,  elapsed time = 2709 ms.
TOP 1

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

(строк обработано: 1)
Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 10, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
   CPU time = 6766 ms,  elapsed time = 3387 ms.
MAX

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

(строк обработано: 1)
Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
   CPU time = 5374 ms,  elapsed time = 2708 ms.
TOP 1

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

(строк обработано: 1)
Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SQL Server Execution Times:
   CPU time = 6797 ms,  elapsed time = 3494 ms.

答案 3 :(得分:3)

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

然而,这整体上是非常糟糕的想法。

答案 4 :(得分:2)

MAX通常更快。

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

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

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

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

答案 5 :(得分: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稍快一点,因为它在执行计划中有最后一步。以下是每个查询执行的执行计划:

SELECT MAX(Id)FROM Table1

聚集索引扫描&gt;&gt;顶部&gt;&gt;流聚合&gt;&gt;选择

SELECT ONE 1 Id FROM Table1 ORDER BY Id DESC

聚集索引扫描&gt;&gt;顶部&gt;&gt;选择

答案 6 :(得分:1)

  

是的,在这种情况下,Id是字段   我已经定义了群集   指数。如果索引是ID DESC那么   什么..是的,它会很好   知道性能如何   如果

受到影响      
      
  1. Id是聚集索引+主键。
  2.   
  3. Id是聚集索引,而不是主键。
  4.   
  5. Id是非聚集索引ASC +主键。
  6.   
  7. Id是非聚集索引ASC,而不是主键。
  8.   
  9. Id是非聚集索引DESC +主键。
  10.   
  11. Id是非聚集索引DESC而不是主键。
  12.   
  13. Id只是AutoIncrement
  14.   

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

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

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

总结:案例1-6取胜!如果你在案例7中,那么你已经从IO的角度失去了。

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

SET STATISTICS IO ON