Являются ли RANK () и DENSE_RANK () детерминированными или недетерминированными?


27

Согласно официальному сообщению Microsoft, BOL DENSE_RANK является недетерминированным ( RANK () ). Но согласно функциям ранжирования Ицик Бен-Гана «... функции RANK () и DENSE_RANK () всегда детерминированы». Кто прав?

То, что я нашел до сих пор: определение Microsoft «Детерминированные функции всегда возвращают один и тот же результат каждый раз, когда они вызываются с определенным набором входных значений и при том же состоянии базы данных».

Так в таблицах теории множеств Сотрудники

Employee            Salary
Sue Right            1.00
Robin Page           1.00
Phil Factor          1.00

и сотрудники2

Employee            Salary
Phil Factor          1.00
Sue Right            1.00
Robin Page           1.00

такие же. Но функции ранжирования возвращают разные значения:

    CREATE TABLE [dbo].[Employees](
    --[ID] [int] IDENTITY(1,1) NOT NULL,
    [Employee] [varchar](150) NOT NULL,
    [Salary] [smallmoney] NULL,
) ON [PRIMARY]

GO
CREATE TABLE [dbo].[Employees2](
    --[ID] [int] IDENTITY(1,1) NOT NULL,
    [Employee] [varchar](150) NOT NULL,
    [Salary] [smallmoney] NULL,
) ON [PRIMARY]

INSERT INTO [dbo].[Employees]
([Employee] ,[Salary])
VALUES
('Sue Right', 1)
, ('Robin Page', 1)
,('Phil Factor', 1 )
GO
INSERT INTO [dbo].[Employees2]
([Employee] ,[Salary])
VALUES
('Phil Factor', 1 )
,('Sue Right', 1)
,('Robin Page', 1)
GO
SELECT RANK() OVER ( ORDER BY Salary) AS [Rank]
, DENSE_RANK() OVER (ORDER BY Salary ) AS [Dense_rank]
, [Employee]
FROM
dbo.Employees

SELECT RANK() OVER ( ORDER BY Salary) AS [Rank]
, DENSE_RANK() OVER (ORDER BY Salary ) AS [Dense_rank]
, [Employee]
FROM
dbo.Employees2

SELECT NTILE(3) OVER ( ORDER BY SALARY )
, [Employee]
FROM
dbo.Employees

SELECT NTILE(3) OVER ( ORDER BY SALARY )
, [Employee]
FROM
dbo.Employees2

Ответы:


23

Согласно официальному сообщению Microsoft, BOL DENSE_RANK является недетерминированным (RANK ()). Но согласно функциям ранжирования Ицик Бен-Гана «... функции RANK () и DENSE_RANK () всегда детерминированы». Кто прав?

Они оба правы, потому что они используют разные значения слова «детерминистический».

С точки зрения оптимизатора SQL Server, «детерминированный» имеет очень точное значение; значение, существовавшее до того, как функции окна и ранжирования были добавлены в продукт. Для оптимизатора свойство «детерминистическое» определяет, может ли функция быть свободно продублирована во внутренних структурах дерева во время оптимизации. Это недопустимо для недетерминированной функции.

Детерминированный здесь означает: точный экземпляр функции всегда возвращает один и тот же вывод для одного и того же ввода, независимо от того, сколько раз он вызывается. Это никогда не верно для оконных функций, по определению, потому что как скалярная функция (одна строка), они не возвращают один и тот же результат в строке или между строками. Чтобы сформулировать это просто, используя ROW_NUMBERв качестве примера:

ROW_NUMBERФункция возвращает разные значения для разных строк (по определению!), Поэтому для целей оптимизации является недетерминировано

В этом смысл BOL.

Ицик высказывает другое мнение о детерминизме результата в целом. Над упорядоченным входным набором (с подходящим разрывом связей) выход является «детерминированной» последовательностью. Это правильное наблюдение, но это не «детерминированное» качество, которое важно при оптимизации запросов.


10

NTILE()интересный случай; похоже, он применяется после сортировки (которая в случае привязки оставляется на собственные устройства SQL Server, и это обычно обусловлено наиболее эффективным выбором индекса для целей сортировки). Вы можете сделать это детерминированным, не заставляя SQL Server делать здесь произвольный выбор - добавьте один или несколько прерывателей связей кOVER() предложение:

OVER (ORDER BY Salary, Employee)

По сути, вам нужно сделать сортировку уникальной. Если у вас есть сотрудники с одинаковыми именами, вам, возможно, придется выбрать другой столбец прерывателя связей или продолжать добавлять столбцы, пока связей действительно не будет.

Для RANK()и DENSE_RANK(), на самом деле, связи являются решающей причиной того, что вы не можете получить разные значения. Постарайтесь не путать детерминизм вывода функции с детерминизмом порядка результатов. Если ваши запросы не имеют ORDER BY, то что не является детерминированным по этому поводу?

1   1   Sue Right
1   1   Robin Page
1   1   Phil Factor

1   1   Phil Factor
1   1   Sue Right
1   1   Robin Page

RANK()и DENSE_RANK()применяя одинаковые значения в обоих случаях, SQL Server просто возвращал вам результаты в другом порядке. Это не имеет ничего общего с ожиданием одного и того же вывода RANK()или DENSE_RANK()с одним и тем же вводом - это просто принятие или ожидание некоторого детерминированного порядка, когда вы сказали SQL Server (пропуская ORDER BYпредложение), что вас не волнует порядок результаты. Смотрите № 3 здесь:


7

Синтаксис:

WindowFunction() OVER (PARTITION BY <some expressions>        -- partition list
                       ORDER BY <some other expressions>)     -- order list

Обе функции RANK()и DENSE_RANK(), по их определениям, гарантированно дают одинаковые результаты, если выражения в OVERпредложении сами по себе являются детерминированными. И это то, что Ицик Бен-Гун имел в виду в своей статье. Эти списки чаще всего являются просто столбцами соответствующих таблиц.

Таким образом, хотя функции общего характера не являются детерминированными, при их реализации можно было бы позаботиться о том, чтобы различать два случая и считать их детерминированными или нет, при рассмотрении списков разделов и порядков.

Я предпочитаю предположить, что разработчики SQL-сервера решили, что проще реализовать их как всегда «недетерминированные», несмотря на то, что это каким-то образом противоречит их определению детерминированных функций. Таким образом, они определены как недетерминированные в MSDN, потому что в текущей реализации механизм всегда рассматривает их как недетерминированные.

Еще один аргумент заключается в том, что две другие оконные функции, ROW_NUMBER()и NTILE(), еще более сложны, потому что для них, имеющих одинаковый вывод, выражение в разделе и порядок по спискам должны быть не только детерминированными, но и уникальными. Таким образом, реализация всех этих деталей далеко не тривиальна.


Я не буду комментировать порядок наборов результатов, так как это не имеет никакого отношения к детерминизму, как четко объяснил Аарон Бертран в своем ответе.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.