AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 77639
Accepted
Pavel Nefyodov
Pavel Nefyodov
Asked: 2014-09-26 05:48:49 +0800 CST2014-09-26 05:48:49 +0800 CST 2014-09-26 05:48:49 +0800 CST

RANK() e DENSE_RANK() são determinísticos ou não determinísticos?

  • 772

De acordo com o oficial da Microsoft, BOL DENSE_RANK não é determinístico ( RANK() ). Mas de acordo com Ranking Functions de Itzik Ben-Gan "... as funções RANK() e DENSE_RANK() são sempre determinísticas". Quem está certo?

O que descobri até agora: Definição da Microsoft "As funções determinísticas sempre retornam o mesmo resultado sempre que são chamadas com um conjunto específico de valores de entrada e recebem o mesmo estado do banco de dados."

Assim, nas tabelas de teoria dos conjuntos Empregados

Employee            Salary
Sue Right            1.00
Robin Page           1.00
Phil Factor          1.00

e Empregados2

Employee            Salary
Phil Factor          1.00
Sue Right            1.00
Robin Page           1.00

são os mesmos. Mas as funções de classificação retornam valores diferentes:

    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
sql-server
  • 3 3 respostas
  • 3135 Views

3 respostas

  • Voted
  1. Best Answer
    Paul White
    2014-09-26T13:29:58+08:002014-09-26T13:29:58+08:00

    De acordo com o oficial da Microsoft, BOL DENSE_RANK é não determinístico (RANK()). Mas de acordo com Ranking Functions de Itzik Ben-Gan "... as funções RANK() e DENSE_RANK() são sempre determinísticas". Quem está certo?

    Ambos estão certos, porque estão usando diferentes sentidos da palavra "determinista".

    Do ponto de vista do otimizador do SQL Server, "determinístico" tem um significado muito preciso; um significado que existia antes das funções de janela e classificação serem adicionadas ao produto. Para o otimizador, a propriedade "determinística" define se uma função pode ser duplicada livremente em suas estruturas internas de árvore durante a otimização. Isso não é legal para uma função não determinística.

    Determinístico aqui significa: a instância exata da função sempre retorna a mesma saída para a mesma entrada, não importa quantas vezes ela seja chamada. Isso nunca é verdade para funções de janelamento, por definição, porque como uma função escalar (de linha única), elas não retornam o mesmo resultado em uma linha ou entre linhas. Simplificando, usando ROW_NUMBERcomo exemplo:

    A ROW_NUMBERfunção retorna valores diferentes para linhas diferentes (por definição!), portanto, para fins de otimização, ela não é determinística

    Este é o sentido que o BOL está usando.

    Itzik está fazendo uma observação diferente sobre o determinismo do resultado como um todo. Sobre um conjunto de entrada ordenado (com desempate adequado) a saída é uma sequência "determinística". Essa é uma observação válida, mas não é a qualidade "determinística" que é importante durante a otimização da consulta.

    • 23
  2. Aaron Bertrand
    2014-09-26T07:20:32+08:002014-09-26T07:20:32+08:00

    NTILE()é um caso interessante; parece aplicar-se após a classificação (que, no caso de empate, é deixada para os próprios dispositivos do SQL Server, e isso geralmente é conduzido pela escolha mais eficiente de índice para fins de classificação). Você pode tornar isso determinístico não forçando o SQL Server a fazer uma escolha arbitrária aqui - adicione um ou mais desempate à OVER()cláusula:

    OVER (ORDER BY Salary, Employee)
    

    Essencialmente, você precisa tornar a classificação exclusiva. Se você tiver funcionários com o mesmo nome, talvez seja necessário escolher uma coluna de desempate diferente ou continuar adicionando colunas até que realmente não haja empates.

    Para RANK()e DENSE_RANK(), os empates são, na verdade, uma razão crucial pela qual você não pode obter valores diferentes. Tente não confundir determinismo da saída da função com determinismo da ordem dos resultados. Se suas consultas não tiverem ORDER BY, o que não é determinístico nisso?

    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()e DENSE_RANK()aplicou os mesmos valores em ambos os casos, o SQL Server apenas retornou os resultados para você em uma ordem diferente. Isso não tem nada a ver com esperar a mesma saída RANK()ou DENSE_RANK()receber a mesma entrada - trata-se apenas de assumir ou esperar alguma ordem determinística quando você disse ao SQL Server (omitindo uma ORDER BYcláusula) que não se importa com a ordem de os resultados. Veja o nº 3 aqui:

    • Terça-feira T-SQL nº 56: Suposições do SQL Server
    • 11
  3. ypercubeᵀᴹ
    2014-09-26T08:33:04+08:002014-09-26T08:33:04+08:00

    Sintaxe:

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

    Ambas as funções, RANK()e DENSE_RANK(), por suas definições, têm a garantia de produzir os mesmos resultados, desde que as próprias expressões na OVERcláusula sejam determinísticas. E é isso que Itzik Ben-Gun quis dizer em seu artigo. Essas listas geralmente são apenas colunas das tabelas envolvidas.

    Assim, embora as funções sejam gerais não sejam determinísticas, sua implementação poderia ter tido o cuidado de distinguir os dois casos e considerá-las determinísticas ou não, ao examinar as listas de partição e ordem.

    Meu palpite é que os desenvolvedores do SQL-Server decidiram que era mais fácil implementá-los como sempre "não determinísticos", apesar de isso contradizer de certa forma sua definição de funções determinísticas. Portanto, eles são declarados como não determinísticos no MSDN porque, na implementação atual, o mecanismo os considera sempre como não determinísticos.

    Mais um argumento é que as outras duas funções de janela, ROW_NUMBER()e NTILE(), são ainda mais complicadas porque, para elas terem saída idêntica, a expressão na partição e a ordem por listas não apenas precisam ser determinísticas, mas também únicas. Portanto, implementar todos esses detalhes está longe de ser trivial.


    Não vou comentar sobre a ordem dos conjuntos de resultados, pois isso não tem nada a ver com o determinismo, como Aaron Bertrand explicou claramente em sua resposta.

    • 7

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve