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 / 39431
Accepted
cubetwo1729
cubetwo1729
Asked: 2013-04-08 07:07:07 +0800 CST2013-04-08 07:07:07 +0800 CST 2013-04-08 07:07:07 +0800 CST

Índice exclusivo para subconsulta com função RANK()

  • 772

Tenho as seguintes tabelas:

CREATE TABLE Revision (
    RevisionId INT PRIMARY KEY IDENTITY,
    UserName NVARCHAR(256) NOT NULL,
    DateTime DATETIME NOT NULL DEFAULT GETDATE()
)

CREATE TABLE MyEntity (
    MyEntityId INT NOT NULL,
    RevisionId INT NOT NULL FOREIGN KEY REFERENCES Revision (RevisionId),
    Deleted BIT NOT NULL DEFAULT 0,
    Name NVARCHAR(256) NOT NULL,
    Body NVARCHAR(MAX) NOT NULL,
    PRIMARY KEY (MyEntityId, RevisionId)
)

Ou seja, a tabela MyEntity contém todas as alterações em uma entidade. Quando uma entidade é criada, modificada ou excluída, um novo registro é inserido em MyEntity e em Revision, para que todo o histórico seja rastreado.

Gostaria de uma view para ter a última versão de cada entidade:

CREATE VIEW MyEntityLatest WITH SCHEMABINDING AS
SELECT
    Latest.MyEntityId,
    Latest.Name,
    Latest.Body
FROM dbo.MyEntity
INNER JOIN (
    SELECT
        MyEntityId,
        RevisionId,
        Name,
        Body,
        RANK() OVER (PARTITION BY MyEntityId ORDER BY RevisionId DESC) AS RevisionIdDesc
    FROM MyEntity
    WHERE Deleted = 0
) AS Latest
    ON dbo.MyEntity.MyEntityId = Latest.MyEntityId
    AND dbo.MyEntity.RevisionId = Latest.RevisionId
WHERE Latest.RevisionIdDesc = 1

No entanto, gostaria de criar um índice exclusivo (e, portanto, restrição) de modo que o Nome seja exclusivo apenas para a revisão mais recente. Não consigo criar um índice na exibição, devido à subconsulta na exibição.

Como posso fazer isso?

sql-server database-design
  • 1 1 respostas
  • 1822 Views

1 respostas

  • Voted
  1. Best Answer
    Jon Seigel
    2013-04-08T08:36:09+08:002013-04-08T08:36:09+08:00

    Confiar na ordem de RevisionIddeterminar a revisão mais recente é incrivelmente perigoso e aponta para um problema de design aqui.

    Como você está usando o SQL Server 2008+, o que eu recomendaria é adicionar um sinalizador de bit IsLatestà MyEntitytabela para identificar a revisão mais recente. Em seguida, crie um índice filtrado exclusivo para restringir cada entidade a ter apenas uma única revisão mais recente (tecnicamente, isso não é necessário devido ao que você pediu, mas é uma ideia muito boa):

    CREATE UNIQUE NONCLUSTERED INDEX UC_MyEntity_IsLatest_MyEntityId
        ON [dbo].[MyEntity](IsLatest, MyEntityId)
            WHERE (IsLatest = 1);
    

    Em seguida, use a mesma técnica para impor a restrição no nome:

    CREATE UNIQUE NONCLUSTERED INDEX UC_MyEntity_IsLatest_Name
        ON [dbo].[MyEntity](IsLatest, Name)
            WHERE (IsLatest = 1);
    

    Você precisará gerenciar o sinalizador desativando-o da revisão "anteriormente mais recente" antes de inserir a "nova revisão mais recente", o que não é muito trabalho extra. Vou deixar para você determinar como isso deve funcionar com a Deletedbandeira envolvida.

    Essa solução reforça a restrição por design e simplificará bastante a definição da exibição, que talvez você nem precise indexar separadamente. (Indexar a Bodycoluna que é nvarchar(MAX)um pouco suspeito, mas é um problema separado.)

    Observação: incluí a IsLatestcoluna na chave dos índices de propósito, pois o otimizador não é inteligente o suficiente para incluir implicitamente o valor dessa coluna do predicado do filtro (como o predicado é arbitrário, presumo que nem tente ). Isso é o que permitirá que o índice seja usado quando você especificar WHERE IsLatest = 1em uma consulta.

    • 1

relate perguntas

  • 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?

  • Quais são algumas maneiras de implementar um relacionamento muitos-para-muitos em um data warehouse?

  • 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

    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

    Conceder acesso a todas as tabelas para um usuário

    • 5 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
    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
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +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