Desnormalização para melhorar o desempenho? Parece convincente, mas não retém água.
Chris Date, que na companhia do Dr. Ted Codd era o proponente original do modelo de dados relacionais, ficou sem paciência com argumentos desinformados contra a normalização e os demoliu sistematicamente usando o método científico: ele obteve grandes bancos de dados e testou essas afirmações.
Acho que ele o escreveu em Relational Database Writings 1988-1991, mas este livro foi posteriormente lançado na edição seis da Introdução aos Sistemas de Banco de Dados , que é o texto definitivo sobre teoria e design de banco de dados, em sua oitava edição enquanto escrevo e provavelmente continuarei impressa nas próximas décadas. Chris Date era um especialista nesse campo quando a maioria de nós ainda andava descalça.
Ele descobriu que:
- Alguns deles são válidos para casos especiais
- Todos eles não pagam para uso geral
- Todos eles são significativamente piores para outros casos especiais
Tudo volta a atenuar o tamanho do conjunto de trabalho. As junções que envolvem chaves selecionadas corretamente com índices configurados corretamente são baratas, não caras, porque permitem a remoção significativa do resultado antes que as linhas sejam materializadas.
A materialização do resultado envolve leituras em disco em massa, que são o aspecto mais caro do exercício por uma ordem de magnitude. A execução de uma junção, por outro lado, exige logicamente a recuperação apenas das chaves . Na prática, nem mesmo os valores-chave são buscados: os valores-chave de hash são usados para comparações de junções, mitigando o custo de junções de várias colunas e reduzindo radicalmente o custo de junções envolvendo comparações de strings. Além de se encaixar muito mais no cache, há muito menos leitura de disco a ser feita.
Além disso, um bom otimizador escolhe a condição mais restritiva e a aplica antes de executar uma junção, aproveitando de maneira muito eficaz a alta seletividade de junções em índices com alta cardinalidade.
É certo que esse tipo de otimização também pode ser aplicado a bancos de dados desnormalizados, mas o tipo de pessoa que deseja desnormalizar um esquema normalmente não pensa em cardinalidade quando (se) configura índices.
É importante entender que as varreduras de tabela (exame de todas as linhas de uma tabela durante a produção de uma junção) são raras na prática. Um otimizador de consulta escolherá uma varredura de tabela apenas quando um ou mais dos seguintes itens forem mantidos.
- Há menos de 200 linhas na relação (nesse caso, uma verificação será mais barata)
- Não há índices adequados nas colunas de junção (se é significativo ingressar nessas colunas, por que eles não são indexados? Corrija-o)
- É necessária uma coerção de tipo antes que as colunas possam ser comparadas (WTF ?! corrija-a ou vá para casa) VEJA AS NOTAS FINAIS DO PROBLEMA DO ADO.NET
- Um dos argumentos da comparação é uma expressão (sem índice)
Realizar uma operação é mais caro do que não realizá-la. No entanto, executar a operação errada , ser forçado a E / S de disco inútil e depois descartar a escória antes de realizar a junção de que você realmente precisa é muito mais caro. Mesmo quando a operação "incorreta" é pré-computada e os índices foram aplicados de maneira sensata, permanece uma penalidade significativa. A desnormalização para pré-calcular uma associação - apesar das anomalias de atualização associadas - é um compromisso com uma associação específica. Se você precisar de uma associação diferente , esse compromisso custará muito .
Se alguém quiser me lembrar que é um mundo em mudança, acho que você descobrirá que conjuntos de dados maiores em hardware mais pesado exageram a disseminação das descobertas de Date.
Para todos vocês que trabalham em sistemas de cobrança ou geradores de lixo eletrônico (que vergonha) e estão indignadamente colocando a mão no teclado para me dizer que sabem que a desnormalização é mais rápida, desculpe, mas você está vivendo em um dos lugares especiais casos - especificamente, o caso em que você processa todos os dados, em ordem. Não é um caso geral, e você está justificado em sua estratégia.
Você não está justificado em generalizar falsamente. Consulte o final da seção de notas para obter mais informações sobre o uso apropriado da desnormalização em cenários de data warehousing.
Eu também gostaria de responder a
As junções são apenas produtos cartesianos com algum brilho labial
Que carga de besteiras. As restrições são aplicadas o mais cedo possível, mais restritivas primeiro. Você leu a teoria, mas não a entendeu. As junções são tratadas como "produtos cartesianos aos quais os predicados se aplicam" apenas pelo otimizador de consultas. Essa é uma representação simbólica (uma normalização, de fato) para facilitar a decomposição simbólica, para que o otimizador possa produzir todas as transformações equivalentes e classificá-las por custo e seletividade, para que possa selecionar o melhor plano de consulta.
A única maneira de obter o otimizador para produzir um produto cartesiano é deixar de fornecer um predicado: SELECT * FROM A,B
Notas
David Aldridge fornece algumas informações adicionais importantes.
De fato, há uma variedade de outras estratégias além de índices e varreduras de tabelas, e um otimizador moderno custará todas elas antes de produzir um plano de execução.
Um conselho prático: se puder ser usado como chave estrangeira, indexe-a, para que uma estratégia de indexação esteja disponível para o otimizador.
Eu costumava ser mais esperto que o otimizador MSSQL. Isso mudou duas versões atrás. Agora isso geralmente me ensina . É, em um sentido muito real, um sistema especialista, codificando toda a sabedoria de muitas pessoas muito inteligentes em um domínio suficientemente fechado para que um sistema baseado em regras seja eficaz.
"Bollocks" pode ter sido sem tato. Me pedem para ser menos arrogante e lembrei que a matemática não mente. Isso é verdade, mas nem todas as implicações dos modelos matemáticos devem necessariamente ser tomadas literalmente. As raízes quadradas dos números negativos são muito úteis se você evitar cuidadosamente examinar o absurdo (trocadilho ali) e se certificar de cancelá-las antes de tentar interpretar sua equação.
A razão pela qual eu respondi de forma tão violenta foi que a declaração redigida diz que
As junções são produtos cartesianos ...
Pode não ser o que quis dizer, mas é o que foi escrito e é categoricamente falso. Um produto cartesiano é uma relação. Uma junção é uma função. Mais especificamente, uma junção é uma função com valor de relação. Com um predicado vazio, ele produzirá um produto cartesiano, e verificar se o faz é uma verificação de correção de um mecanismo de consulta de banco de dados, mas ninguém na prática cria uniões irrestritas porque não tem valor prático fora da sala de aula.
Eu falei isso porque não quero que os leitores caiam na armadilha antiga de confundir o modelo com o que foi modelado. Um modelo é uma aproximação, deliberadamente simplificada para manipulação conveniente.
O ponto de corte para a seleção de uma estratégia de junção de varredura de tabela pode variar entre os mecanismos de banco de dados. Ele é afetado por várias decisões de implementação, como fator de preenchimento do nó da árvore, tamanho do valor-chave e sutilezas do algoritmo, mas, em termos gerais, a indexação de alto desempenho tem um tempo de execução de k log n + c . O termo C é uma sobrecarga fixa composta principalmente de tempo de configuração, e o formato da curva significa que você não recebe um pagamento (comparado a uma pesquisa linear) até que n esteja na casa das centenas.
Às vezes, a desnormalização é uma boa ideia
A desnormalização é um compromisso com uma estratégia de junção específica. Como mencionado anteriormente, isso interfere com outras estratégias de junção. Mas se você tiver intervalos de espaço em disco, padrões previsíveis de acesso e uma tendência a processar grande parte ou a totalidade dele, a pré-computação de uma junção pode valer muito a pena.
Você também pode descobrir os caminhos de acesso que sua operação normalmente usa e pré-calcular todas as junções para esses caminhos de acesso. Essa é a premissa por trás dos data warehouses, ou pelo menos é quando eles são criados por pessoas que sabem por que estão fazendo o que estão fazendo, e não apenas por uma questão de conformidade com os chavões.
Um data warehouse adequadamente projetado é produzido periodicamente por uma transformação em massa de um sistema de processamento de transações normalizado. Essa separação dos bancos de dados de operações e relatórios tem o efeito muito desejável de eliminar o conflito entre OLTP e OLAP (processamento de transações online, por exemplo, entrada de dados e processamento analítico online, por exemplo, relatório).
Um ponto importante aqui é que, além das atualizações periódicas, o armazém de dados é somente leitura . Isso torna discutível a questão das anomalias de atualização.
Não cometa o erro de desnormalizar seu banco de dados OLTP (o banco de dados no qual a entrada de dados ocorre). Pode ser mais rápido para execuções de cobrança, mas se você fizer isso, receberá anomalias de atualização. Já tentou fazer com que o Reader's Digest parasse de lhe enviar coisas?
Hoje em dia, o espaço em disco é barato, portanto, se nocauteie. Mas a desnormalização é apenas parte da história dos data warehouses. Ganhos de desempenho muito maiores são derivados de valores acumulados pré-computados: totais mensais, esse tipo de coisa. É sempre uma questão de reduzir o conjunto de trabalho.
Problema no ADO.NET com incompatibilidades de tipo
Suponha que você tenha uma tabela do SQL Server contendo uma coluna indexada do tipo varchar e use AddWithValue para passar um parâmetro que restringe uma consulta nessa coluna. As seqüências de caracteres C # são Unicode, portanto, o tipo de parâmetro inferido será NVARCHAR, que não corresponde a VARCHAR.
O VARCHAR para o NVARCHAR é uma conversão cada vez maior, por isso ocorre implicitamente - mas diga adeus à indexação e boa sorte para descobrir o porquê.
"Conte os hits do disco" (Rick James)
Se tudo estiver armazenado em cache na RAM, JOINs
será bastante barato. Ou seja, a normalização não possui muita penalidade de desempenho .
Se um esquema "normalizado" causar muito JOINs
impacto no disco, mas o esquema "desnormalizado" equivalente não precisar atingir o disco, a desnormalização vence uma competição de desempenho.
Comentário do autor original: Os modernos mecanismos de banco de dados são muito bons em organizar o seqüenciamento de acesso para minimizar as falhas de cache durante as operações de junção. O exposto acima, embora verdadeiro, pode ser mal interpretado, pois implica que as junções são necessariamente problemáticas em grandes volumes de dados. Isso levaria a uma tomada de decisão ruim por parte de desenvolvedores inexperientes.