É uma má prática agregar dados de tabelas diferentes em uma?

12

fundo

Escrevo muitos relatórios grandes para e geralmente mantenho um banco de dados grande de registros de saúde (escreva SPs, funções, trabalhos etc.). O esquema original e o software que o utiliza são de um fornecedor diferente, portanto não posso mudar muito estruturalmente. Existem muitos registros que exigem rastreamento, como laboratórios, procedimentos, vacinas etc., e estão espalhados por dezenas de tabelas, muitas das quais estão inchadas e mal indexadas (consegui corrigir isso de alguma forma).

O problema

O problema é que, como temos pouco controle sobre o banco de dados e, como ele pode mudar de qualquer atualização ou patch, torna difícil escrever e manter esses relatórios difíceis e entediantes - especialmente quando há muita sobreposição. Só é preciso um patch e estou preso reescrevendo grandes porções de uma dúzia de relatórios. Além disso, as consultas rapidamente ficam ofuscadas e lentas à medida que as junções, aninhados selecionam e se aplicam.

Minha "solução"

Meu plano era gravar todos esses registros em uma tabela "catch-all" e gravar gatilhos nas tabelas originais para manter os registros nessa tabela agregada. É claro que eu precisaria garantir que meus gatilhos estivessem intactos após as atualizações, mas isso seria muito mais fácil do ponto de vista de manutenção e apenas referenciando os dados.

A tabela seria fina e longa, armazenando apenas os dados necessários, algo como isto:

CREATE TABLE dbo.HCM_Event_Log (
    id INT IDENTITY,
    type_id INT NULL,
    orig_id VARCHAR(36) NULL,
    patient_id UNIQUEIDENTIFIER NOT NULL,
    visit_id UNIQUEIDENTIFIER NULL,
    lookup_id VARCHAR(50) NULL,
    status VARCHAR(15) NULL,
    ordered_datetime DATETIME NULL,
    completed_datetime DATETIME NULL,
    CONSTRAINT PK_HCM_Event_Log PRIMARY KEY CLUSTERED (id)
)

Então, eu teria várias tabelas relacionais para coisas como o type_id e os agrupamentos de itens.

Estou começando a adivinhar essa idéia, já que várias dessas tabelas são gravadas um pouco, os SPs e os relatórios que eu estaria escrevendo também referenciam os dados. Por isso, estou preocupado que essa tabela se torne um pesadelo de bloqueio e desempenho de registros com tanta E / S.

Minha pergunta

É uma má ou uma boa ideia? Sei que todas as situações são diferentes no SQL Server (2008 r2 Standard Edition BTW) e a regra "às vezes", mas estou apenas procurando conselhos gerais.

Comecei a considerar o uso de um corretor de serviços, mas só estaria executando atualizações / inserções simples ( consulte a alternativa à resposta aceita ). Os dados em muitos casos precisam ser em tempo real, portanto, o uso de um banco de dados de backup não funcionaria realmente. O desempenho já é um problema para nós, mas a maior parte está relacionada ao hardware que será resolvida em breve.

jreed121
fonte
1
Você pode aplicar interrupções planejadas? Se nenhuma dessas atualizações puder eliminar um gatilho e você não atualizará seus agregados, possivelmente levando a dados incorretos.
Erik
Você está pensando em colocar todas as informações sobre laboratórios, procedimentos, vacinas e pacientes em uma única tabela? Péssima ideia. Você pode usar um esquema em estrela, se isso for adequado ao tipo de consultas que você está executando.
Michael Green
1
Você já pensou em criar algumas visualizações indexadas? Isso colocaria uma camada lógica entre seu código e o do fornecedor, para que você possa atualizar a exibição apenas se o fornecedor alterar as coisas abaixo. Além disso, as visualizações indexadas seriam pré-preenchidas para você e forneceriam um bom desempenho de leitura. Uma das considerações mais importantes ao fazer isso é a quantidade de carga que ela coloca nas operações de gravação das tabelas de banco de dados do fornecedor. No entanto, isso provavelmente seria um mais limpo e mais fácil de manter do que solução usando gatilhos, etc.
Micah Nikkel
Desculpe pela resposta tardia, obrigado pelo feedback. @Erik - Sim, planejamos atualizações e verifico se todas as minhas alterações anteriores ainda estão em vigor por meio de uma série de scripts de lista de verificação que eu corro, para que não haja surpresas por lá e eu continuarei com CREATE scripts para todos os gatilhos.
precisa saber é o seguinte
@ MichaelGreen - Vou examinar um esquema em estrela, mas estou curioso por que você acha que ter todos esses dados em uma tabela é uma má ideia? O ambiente do aplicativo é completamente isolado em uma VPN, de qualquer maneira não é acessível fora da rede. Se algo der errado com a mesa, não será o fim do mundo, porque eu poderia escrever tudo de volta. A tabela não será usada para dados de missão crítica ou, pelo menos, não será o único nem principal local em que os dados são armazenados.
precisa saber é o seguinte

Respostas:

8

Se eu entendi direito,

  • você tem um grande sistema de terceiros,
  • você não tem muito controle sobre isso,
  • você faz relatórios complexos que lêem dados diretamente desse banco de dados de terceiros,
  • suas consultas dependem da estrutura interna do banco de dados de terceiros.

Eu abordaria assim:

  • Configure meu próprio banco de dados separado, do qual tenho controle total.
  • Configure um processo de sincronização que leia dados de tabelas e colunas relevantes do banco de dados de terceiros e insira / atualize no meu.
  • Desenvolva meus relatórios complexos com base na estrutura estável do meu banco de dados.

Nesse caso, você pode ajustar a estrutura e os índices do seu banco de dados para melhorar o desempenho dos seus relatórios, sem afetar o sistema de terceiros. A menos que a estrutura de dados original mude drasticamente, a lógica de suas consultas para seus relatórios não mudará se o banco de dados de terceiros for alterado. Você precisaria ajustar apenas o processo de sincronização.

O processo de sincronização é efetivamente o processo de conversão - você converte dados do banco de dados de terceiros na estrutura necessária. Parte desse processo de conversão pode estar corrigindo quaisquer problemas de normalização que o banco de dados de terceiros original possa ter. Somente essa parte do sistema precisa conhecer e depender da estrutura interna do sistema de terceiros. Seus principais relatórios e consultas principais dependeriam apenas do seu banco de dados.

Portanto, o ponto principal é - separe e limite a parte do seu sistema que depende de componentes internos do sistema de terceiros.

atualizar

Em relação à exigência em tempo real. BTW, eu sempre pensei que a definição de "tempo real" é "tempo de resposta garantido", não "um pequeno tempo de resposta". Depende da sua aplicação, é claro. Na minha prática, basta sincronizar dois bancos de dados dentro de um minuto após a alteração detectada. Se um usuário vê um relatório na tela e algumas alterações de dados subjacentes, o relatório deve ser executado de alguma forma para refletir essa alteração. Você pode pesquisar alterações ou ouvir algum evento / mensagem, ainda que a consulta do relatório precise ser executada novamente para mostrar as alterações mais recentes.

Você já pretende gravar gatilhos para capturar alterações nas tabelas originais e gravá-las em uma tabela genérica. Portanto, capture as alterações conforme desejado, mas grave-as em tabelas normalizadas adequadamente, e não em uma única.

Portanto, esse é um caso extremo - a conversão da estrutura de dados de terceiros em sua estrutura de dados interna é realizada nos gatilhos acionados em INSERT/UPDATE/DELETEtabelas de terceiros. Pode ser complicado. O código dos gatilhos dependeria da estrutura interna dos dois sistemas. Se a conversão não for trivial, pode atrasar o original INSERT/UPDATE/DELETEaté o ponto de falha. Se houver um bug no seu gatilho, isso poderá afetar a transação original ao ponto da falha. Se o sistema de terceiros for alterado, isso poderá interromper o gatilho, o que causaria falha nas transações do sistema de terceiros.

Caso menos extremo. Para tornar o código de seus gatilhos mais simples e menos propenso a erros, grave todas as alterações capturadas em algumas tabelas de teste / auditoria / diff, defina algum sinalizador / envie uma mensagem informando que há alterações pendentes e inicie o processo de conversão principal através dessas tabelas intermediárias e realize a conversão. O principal aqui é que o processo de conversão potencialmente pesado deve ocorrer fora do escopo da transação original.

À primeira vista, parece bastante com a sua sugestão original na pergunta. Mas a diferença é: as tabelas de captura de todos retêm dados apenas temporariamente; a quantidade de dados é pequena - exatamente o que mudou; não precisa ser uma única tabela; eventualmente, os dados serão armazenados em tabelas permanentes, normalizadas e adequadamente separadas, das quais você tem controle total, independentes do sistema de terceiros e que podem ser ajustadas para suas consultas.

Vladimir Baranov
fonte
Se você seguir a rota de transferência em lote, obtivemos sucesso com o Rastreamento de alterações (e o Change Data Capture, dependendo de suas necessidades) com contagens de transações bastante altas (100 mil por dia). É mais simples do que implementar suas próprias tabelas de teste / auditoria / diff e pode ser implantado sem alterações ou gatilhos no código do aplicativo.
Michael Green
Seja ele gatilhos ou CDC, a única maneira de você realmente se aproximar em tempo real é de streaming ou filas. Baseado em fila é um bom compromisso para latência e relação custo-benefício. Seu tempo será gasto em métodos para processar a fila mais rapidamente. deixando a maior parte do trabalho assíncrona do aplicativo e colocando menos carga nas transações do usuário. No passado, eu fiz exatamente isso com o Allscripts Sunrise EMR com um serviço que processava a fila com algumas chamadas paralelas de C #. latência típico para novos dados a serem processados e disponíveis no armazém foi sub 30 seg
Brad D
Talvez eu tenha afirmado em "tempo real", não estou muito preocupado com milissegundos ou até cinco segundos, mas tenho muitas consultas nas quais nossa equipe confia para impulsionar o fluxo de trabalho. Se um cliente fez algo com eles (procedimento, imunização etc.), precisamos mostrar isso em um curto período. As conversões são triviais e / ou nem mesmo conversões. Não estou preocupado demais com as alterações nas tabelas de fornecedores, pois elas não mudam com tanta frequência, e tenho que fazê-lo agora de qualquer maneira, mas pensei que era mais fácil atualizar / recriar um gatilho do que uma dúzia de relatórios / consultas / SPs. Eu executo verificações após cada atualização.
precisa saber é o seguinte
@ jreed121, também acho que é mais fácil atualizar gatilhos do que relatórios. Você provavelmente terá um gatilho em cada tabela de origem para capturar as alterações; portanto, provavelmente haverá mais de um gatilho. Ainda assim, não tente gravar todas essas alterações capturadas em uma enorme tabela desnormalizada. Escreva-os em um conjunto de tabelas normalizado corretamente. Seus relatórios devem se basear nessas tabelas normalizadas que você controla e não devem depender das tabelas originais que podem mudar.
Vladimir Baranov
3

De qualquer forma, coloque-o em um conjunto padronizado de tabelas para que você possa ajustar o estágio de importação em vez de precisar alterar relatórios e consultas complexas. Mas os dados ainda devem ser normalizados, o que exigirá tabelas múltiplas (mas com bons índices).

Como outros já mencionaram, não use gatilhos, sincronize em lotes.

Não se preocupe com muitas associações, quando os dados são normalizados e indexados adequadamente, eles não adicionam nenhum custo ou ônus de gerenciamento significativo.

O momento de desnormalizar algo como um data warehouse é quando você precisa fazer muitos tipos diferentes de consulta nos dados que não pode prever. Ele tem suas próprias desvantagens e despesas gerais e deve ser usado onde for apropriado, não como um item essencial.

JamesRyan
fonte
3

Eu trabalhei com uma situação muito semelhante como essa no passado em uma empresa de manufatura 24x7 e finalmente decidi usar a replicação transacional. É possível configurar o DDL para ser replicado de forma que você possa enviar o que quer que os patches mudem para o assinante. Obviamente, existem prós e contras em tudo e é preciso ponderá-los para determinar o que você pode apoiar e o que funciona melhor para a empresa.

Pelo lado positivo:

  1. "Tempo real" é limitado apenas ao desempenho de confirmação de rede e transação no assinante. Na minha experiência com o sistema TPS moderadamente alto, fomos replicados em menos de 10 segundos dos dados "em tempo real".
  2. Separação de cargas de trabalho. No momento, você está executando uma carga de trabalho mista em um servidor. Se você pode separar essas duas preocupações, poderá obter os benefícios de desempenho nos dois sistemas de remover uma carga de trabalho da equação
  3. Ao controle. Você poderá fazer modificações de indexação / estatísticas / manutenção para se adequar à sua carga de trabalho de relatórios.

Existem contras, no entanto:

  1. Custo. Outra licença e mais hardware (virtual ou não).
  2. Replicação. Funciona muito bem quando é configurado corretamente, mas pode ser um aborrecimento chegar a esse ponto.
  3. Manutenção. Se você fizer alterações prejudiciais nas estruturas (por exemplo, soltar um índice), elas retornarão quando o instantâneo for aplicado (após a publicação ter sido alterada ou quando os artigos forem alterados).
swasheck
fonte
2

Meu plano era gravar todos esses registros em uma tabela "catch-all" e gravar gatilhos nas tabelas originais para manter os registros nessa tabela agregada.

Os gatilhos têm tantos problemas que você deve evitá-los:

  • Um erro em um gatilho pode fazer com que a transação original seja interrompida
  • Os gatilhos que lidam corretamente com operações de várias linhas são difíceis de escrever
  • Os gatilhos podem confundir aplicativos clientes modificando o conjunto de linhas retornado (por exemplo, um gatilho substitui o número de linhas afetadas)
  • Quando um gatilho aciona outro, é difícil prever os resultados

Uma opção melhor é um trabalho que copia os dados periodicamente para uma nova tabela. Seus relatórios podem ser executados da cópia. Um trabalho que copia linhas é fácil de gravar e manter, e não há risco de afetar a operação do aplicativo de terceiros.

Andomar
fonte
1. Os gatilhos seriam simples, portanto os erros gerados seriam mínimos, se existentes. 2. O gatilho em si não lidaria com várias linhas (uma linha atualizada no IE na tabela com o gatilho não faria com que várias linhas fossem atualizadas em outro local), mas várias linhas poderiam ser inseridas / atualizadas / excluídas de uma só vez na origem tabela - é isso que você quer dizer? 3. Não foi possível lidar com isso NOCOUNT? 4. Não haveria gatilhos na tabela de destino, e eu poderia garantir o mesmo para os outros.
precisa saber é o seguinte
Como você diz, é teoricamente possível fazer com que os gatilhos funcionem. Na prática, eles nunca fazem isso.
Andomar 20/08/2015