você: possa precisar restaurar o registro em algum momento (undelete) obter informações dos registros deletados (várias vezes requisições dos clientes e não dos usuários).
A decisão sobre usar uma ou outra depende
individualmente de cada caso. Mas na maioria dos casos o mais recomendado é usar a exclusão lógica quando há a mínima probabilidade que seja de haver restauração dos registros deletados. Uma query WHERE tabela.Excluido = 0 não customa denegrir performance, recaindo a preocupação mais sobre o tamanho de dados a armazenar. E claro, sobre a possibilidade de restaurar.
Uma alternativa também usada, em tabelas que possam vir
a ter um tamanho gigante com um proporção alta de excluídos, os registros podem ser movidos para outra tabela exclusiva para Excluidos para não afetar a performance da tabela principal.
Porém nesse caso, deve-se tomar o cuidado porque pode
ser possível que não possam ser restaurados facilmente caso tenham um PK com autoincremento. Normalmente são usados para consultas de "históricos". Esse caso pode ser usado também em questões legais, como guardar dados sobre os logins efetuados pelos usuários num site durante X anos em constraste com o dados somente informativos ao usuário/cliente do seu último login num site. antagens de usar uma deleção lógica:
Auditorias: se você usar um campo data-hora para
guardar a deleção, ao invés de um simples booleano / string, você pode saber quando foi deletado. E você pode usar índices e pesquisas sem problemas com isto, pois sua pesquisa será do tipo WHERE dtExclusao = NULL ou algo assim. Deleção mais fácil: não precisa se preocupar em manter algumas integridades na hora de fazer a deleção, já que não é feita uma deleção em cascata. possibilidade de no futuro implementar alguma solução de inteligência/BI, já que haverá um histórico de todos os dados que poderão ser utilizados
Desvantagens:
você vai ter que controlar a deleção no seu código,
sempre lembrando de ter um WHERE para poder deixar os deletados de fora se a tabela for muito grande e fragmentada (com alguns dados não-deletados bem espaçados no meio de vários dados deletados), a performance poderá cair, pois as tabelas são guardadas em "páginas" no disco, com algumas sendo carregadas na memória. Se os dados não-deletados estiverem todos em poucas "páginas", ótimo. Mas se o seu índice disser que tem um dado válido em cada página, o seu banco vai perder um tempo enorme lendo cada página para memória, extraindo só a linha que você precisa, e carregando a próxima página. Neste caso, para contornar isto, valeria a pena ter uma tabela de dados ativos e jogar os que forem apagados para outra tabela. os dados da deleção em cascata continuam todos nas mesmas tabelas, ou seja, um registro é marcado como apagado na tabela pai, mas nas tabelas filhas nada indica se o dado ainda está sendo usado ou não, e as tabelas podem ficar grandes, sem conseguir jogar dados para uma tabela especial dos que foram apagados tempo / custo de backup: já que os backups completos (full) terão um monte de dados que na verdade foram deletados demora para gravar dados: se os índices são grandes (já que as tabelas podem ser grandes, armazenando todos os registros excluídos), a cada gravação de um novo dado pode exigir um grande tempo de construção do índice, e assim cada ação de gravar pode ter uma performance baixa