Ответ 1
Не будет никакой разницы, поскольку вы можете проверить себя, проверив планы выполнения. Если id
- это кластеризованный индекс, вы должны увидеть упорядоченное сканирование индексированных кластеров; если он не проиндексирован, вы все равно увидите либо сканирование таблицы, либо кластерное сканирование индекса, но оно не будет упорядочено в любом случае.
Подход TOP 1
может быть полезен, если вы хотите вытащить другие значения из строки, что проще, чем потянуть max в подзапрос и затем присоединиться. Если вам нужны другие значения из строки, вам нужно диктовать, как обращаться со связями в обоих случаях.
Сказав это, есть некоторые сценарии, в которых план может быть другим, поэтому важно проверить в зависимости от того, индексирован ли столбец и монотонно ли он увеличивается. Я создал простую таблицу и вставил 50000 строк:
CREATE TABLE dbo.x
(
a INT, b INT, c INT, d INT,
e DATETIME, f DATETIME, g DATETIME, h DATETIME
);
CREATE UNIQUE CLUSTERED INDEX a ON dbo.x(a);
CREATE INDEX b ON dbo.x(b)
CREATE INDEX e ON dbo.x(e);
CREATE INDEX f ON dbo.x(f);
INSERT dbo.x(a, b, c, d, e, f, g, h)
SELECT
n.rn, -- ints monotonically increasing
n.a, -- ints in random order
n.rn,
n.a,
DATEADD(DAY, n.rn/100, '20100101'), -- dates monotonically increasing
DATEADD(DAY, -n.a % 1000, '20120101'), -- dates in random order
DATEADD(DAY, n.rn/100, '20100101'),
DATEADD(DAY, -n.a % 1000, '20120101')
FROM
(
SELECT TOP (50000)
(ABS(s1.[object_id]) % 10000) + 1,
rn = ROW_NUMBER() OVER (ORDER BY s2.[object_id])
FROM sys.all_objects AS s1
CROSS JOIN sys.all_objects AS s2
) AS n(a,rn);
GO
В моей системе это создало значения в a/c от 1 до 50000, b/d между 3 и 9994, e/g с 2010-01-01 по 2011-05-16 и f/h с 2009-04 -28 до 2012-01-01.
Сначала сравним индексированные монотонно возрастающие целые столбцы a и c. a имеет кластерный индекс, c не:
SELECT MAX(a) FROM dbo.x;
SELECT TOP (1) a FROM dbo.x ORDER BY a DESC;
SELECT MAX(c) FROM dbo.x;
SELECT TOP (1) c FROM dbo.x ORDER BY c DESC;
Результаты:
Большая проблема с 4-м запросом заключается в том, что, в отличие от MAX
, для него требуется сортировка. Здесь 3 по сравнению с 4:
Это будет распространенной проблемой во всех этих вариантах запроса: a MAX
против необработанного столбца сможет копировать сканирование кластерного индекса и выполнять агрегацию потока, тогда как TOP 1
необходимо выполнить сортировка, которая будет дороже.
Я проверил и увидел те же самые результаты при тестировании b + d, e + g и f + h.
Итак, мне кажется, что помимо создания большего количества кода соответствия стандартам существует потенциальная эффективность использования MAX
в пользу TOP 1
в зависимости от базовой таблицы и индексов (которая может измениться после вас 'выложите свой код в производство). Поэтому я бы сказал, что без дополнительной информации MAX
предпочтительнее.
(И, как я уже говорил, TOP 1
действительно может быть поведением, которое вам нужно, если вы тянете дополнительные столбцы. Вам нужно будет протестировать методы MAX
+ JOIN
, если это вы после.)