Pergunta

Eu tenho uma pergunta sobre as duas colunas adicionais (timeCreated, timeLastUpdated) para cada registro que vemos em muitas soluções. Minha pergunta:? Existe uma alternativa melhor

cenário: Você tem uma enorme DB (em termos de tabelas, e não registros), e, em seguida, o cliente vem e lhe pede para adicionar "timestamping" para 80% de suas tabelas

.

Eu acredito que isso pode ser feito usando uma tabela separada (timestamps). Esta tabela teria, além da coluna timestamp óbvio, o nome da tabela e a chave primária para a tabela que está sendo atualizado. (Estou assumindo aqui que você usar um int como chave primária para a maioria de suas tabelas, mas o nome da tabela seria mais provável tem que ser uma string).

Para retratar isto supor que este cenário básico. Teríamos duas tabelas:

PAGAMENTO: - (seus registros usuais)
Timestamp: - {timestamp atual} + {TABLE_UPDATED, id_of_entry_updated, timestamp_type}

Note que neste projeto você não precisa dessas duas colunas "extra" em seu objeto de pagamento nativa (que, por sinal, pode fazê-lo através de sua solução ORM), porque você agora está indexando por TABLE_UPDATED e id_of_entry_updated. Além disso, timestamp_type vai dizer se a entrada é para inserção (por exemplo "1"), update (por exemplo "2"), e qualquer outra coisa que você pode querer adicionar, como "eliminação".

Gostaria de saber o que você pensa sobre o seu design. Estou mais interessado em melhores práticas, o que funciona e escalas ao longo do tempo. Referências, links, entradas de blog são mais do que bem-vindo. Eu sei de pelo menos uma patente (pendente) que tenta resolver este problema, mas parece que os detalhes não são públicas neste momento.

Cheers, Eduardo

Foi útil?

Solução

Enquanto você está nisso, também registram o usuário que fez a alteração.

A falha com o design de mesa separado (além do desempenho juntar-se destacado por outros) é que faz a suposição de que todas tabela tem uma coluna de identidade para a chave. Isso nem sempre é verdade.

Se você usar SQL Server, a nova versão 2008 suporta algo que eles chamam Change Data Capture que deve tirar um monte da dor que você está falando. Eu acho que a Oracle pode ter algo semelhante também.


Update: Aparentemente, a Oracle chama-lhe a mesma coisa que SQL Server. Ou melhor, SQL Server chama-lhe a mesma coisa que Oracle, desde a implementação da Oracle veio primeiro;)
http://www.oracle.com/technology/oramag/ oracle / 03-nov / o63tech_bi.html

Outras dicas

Eu tenho usado um projeto onde cada tabela a ser auditados teve duas tabelas:

create table NAME (
  name_id int,
  first_name varchar
  last_name varchar
  -- any other table/column constraints
)

create table NAME_AUDIT (
  name_audit_id int
  name_id int
  first_name varchar
  last_name varchar
  update_type char(1) -- 'U', 'D', 'C'
  update_date datetime
  -- no table constraints really, outside of name_audit_id as PK
)

Um gatilho de banco de dados é criado que preenche NAME_AUDIT toda vez que nada é feito para NAME. Desta forma, você tem um registro de cada mudança feita em cima da mesa, e quando. A aplicação não tem conhecimento real desta, uma vez que é mantido por um gatilho de banco de dados.

Ele funciona razoavelmente bem e não requer quaisquer alterações ao código do aplicativo para implementar.

Eu acho que eu prefiro adicionando a data e hora às tabelas individuais. Juntando-se em sua mesa de timestamp em uma chave composta - um dos quais é uma string -. Vai ser mais lento e se você tem uma grande quantidade de dados que acabará por ser um problema real

Além disso, muitas das vezes, quando você está olhando para timestamps, é quando você está depurando um problema na sua aplicação e você vai querer os dados ali mesmo, ao invés de sempre ter que se juntar contra a outra tabela.

A vantagem do método que você sugere é que lhe dá a opção de adicionar outros campos à sua mesa TIMESTAMP, como rastreamento do usuário que fez a alteração. Você também pode acompanhar edições para domínios sensíveis, por exemplo, que repriced este contrato?

Registro de alterações de registro em um meio de arquivos separados, você pode mostrar várias alterações em um registro, como:

mm / dd / aa hh: mm: ss Adicionado por XXX mm / dd / aa hh: mm: ss campo preço alterado por XXX, mm / dd / aa hh: mm: ss Registro excluído por XXX

Uma desvantagem é o código extra que o vai fazer uma inserção na sua tabela de marcas de tempo para refletir mudanças em suas tabelas principais.

Se você configurar o material carimbo de tempo para fugir dos disparos, que qualquer ação que pode desencadear um gatilho (Lê?) Podem ser registrados. Também pode haver algumas vantagens de bloqueio.

(Leve tudo isso com um grão de sal, não sou DBA ou guru SQL)

Sim, eu como aquele design, e usá-lo com alguns sistemas. Normalmente, alguma variante:

LogID  int
Action varchar(1)     -- ADDED (A)/UPDATED (U)/DELETED (D)
UserID varchar(20)    -- UserID of culprit :)
Timestamp datetime    -- Date/Time
TableName varchar(50) -- Table Name or Stored Procedure ran
UniqueID int          -- Unique ID of record acted upon
Notes varchar(1000)   -- Other notes Stored Procedure or Application may provide

Um pesadelo com seu projeto é que cada inserção, atualização ou exclusão teria que bater nessa tabela. Isso pode causar grandes problemas de desempenho e bloqueio. É uma má idéia para generalizar uma mesa assim (não apenas para timestamps). Também seria um pesadelo para obter os dados de fora.

Se o seu código iria quebrar no nível GUI dos campos acrescentando que não deseja que o usuário veja, você está incorretamente escrever o código para o seu GUI que deve especificar apenas o número mínimo de colunas que você precisa e nunca escolha *.

Eu acho que o extra de junta que você terá que realizar para obter a data e hora será uma pequena queda de performance e uma dor no pescoço. Outros, que eu não vejo nenhum problema.

Nós fizemos exatamente o que você fez. É ótimo para o modelo de objeto e a capacidade de adicionar novos selos e tipos differant_nup de selos para o nosso modelo com código mínimo. Nós também estavam monitorando o usuário que fez a alteração, e um monte de nossa lógica foi fortemente baseado nestes selos. Ele woked muito bem.

Uma desvantagem está relatando, e / ou mostrando um monte de selos differant_nup em na tela. Se você está fazendo isso da maneira que fizemos isso, causou uma série de junções. Além disso, alterações de volta final foi uma dor.

A nossa solução é manter uma tabela de "Operação", para além de nossa mesa "Sessão". UPDATE, INSERT e instruções DELETE são todos gerenciados através de um objeto "Transação" e cada um deles instrução SQL é armazenado na tabela "Transação" uma vez que foi executada com êxito no banco de dados. Esta tabela "Transação" tem outros campos, como transactiontType (I para INSERT, D para DELETE U para UPDATE), transactionDateTime, etc, e uma chave estrangeira "sessionId", dizendo-nos finalmente que enviaram a instrução. É ainda possível, através de um código, para identificar quem fez o quê e quando (Gus criou o registro na segunda-feira, Tim mudou o Preço Unitário na terça-feira, Liz acrescentou um desconto extra na quinta-feira, etc).

Pros para esta solução são:

  1. Você é capaz de dizer "o que quem e quando", e mostrá-lo para seus usuários! (Você vai precisar de algum código para analisar instruções SQL)
  2. Se os dados são replicados, e replicação falhar, você pode reconstruir seu banco de dados através desta tabela

Contras são

  1. 100 000 atualizações de dados por mês média de 100 000 registos em Tbl_Transaction
  2. Finalmente, esta tabela tende a ser de 99% do seu volume de banco de dados

A nossa escolha: todos os registros de mais de 90 dias são automaticamente apagadas todas as manhãs

Philippe,

Não basta excluir aqueles com mais de 90 dias, movê-los primeiro para um DB separado ou gravá-los em arquivo de texto, fazer algo para preservá-los, basta movê-los para fora da principal produção DB.

Se alguma vez se resume a isso, na maioria das vezes é um caso de "ele com mais vitórias de documentação"!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top